home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / samba / patches / samba-1.036 / samba-1
Text File  |  1995-11-14  |  157KB  |  5,332 lines

  1. diff -u -r --new-file last-version/docs/BROWSING.txt samba-1.9.15/docs/BROWSING.txt
  2. --- last-version/docs/BROWSING.txt    Tue Jan 10 22:05:51 1995
  3. +++ samba-1.9.15/docs/BROWSING.txt    Tue Nov 14 22:29:10 1995
  4. @@ -1,18 +1,17 @@
  5.  BROWSING
  6.  ========
  7.  
  8. -Samba has recently begun support for browsing. The browsing is
  9. -supported by nmbd and is also controlled by options in the smb.conf
  10. -file (see smb.conf(5)).
  11. -
  12. -Samba does not act as a browse master for a workgroup, so it can only
  13. -participate in workgroups which already have a browse master. If you
  14. -have any WfWg or WinNT machines in your workgroup that exports a share
  15. -then you already have a browse master so this shouldn't be a problem.
  16. -
  17. -To get browsing to work you need to run nmbd as usual, but need to
  18. -either give the -G option to elect which workgroup Samba will be part
  19. -of, or use a lmhosts file.
  20. +Samba now fully supports browsing. The browsing is supported by nmbd
  21. +and is also controlled by options in the smb.conf file (see
  22. +smb.conf(5)).
  23. +
  24. +Samba can act as a browse master for a workgroup, but currently cannot
  25. +act as a domain controller. The ability to be a domain controller will
  26. +be added in a later version.
  27. +
  28. +To get browsing to work you need to run nmbd as usual, but will need
  29. +to use the "workgroup" option in smb.conf to control what workgroup
  30. +Samba becomes a part of.
  31.  
  32.  The -G option is most useful for simple setups where Samba is browsable
  33.  in only one workgroup. In more complex cases the lmhosts file is
  34. @@ -33,7 +32,12 @@
  35.  # our own net address
  36.  0.0.0.0 MYGROUP G
  37.  
  38. -Samba has a useful option for a Samba server to offer itself for
  39. +Note in the above that I overrode what workgroup Samba is in using the
  40. +G flag. Also note that the 0.0.0.0 address is used, which will be
  41. +automatically replaced with the broadcast address for groups, and with
  42. +the local IP address for other entries.
  43. +
  44. +Samba also has a useful option for a Samba server to offer itself for
  45.  browsing on another subnet.
  46.  
  47.  This works by the lmhosts file specifying a broadcast address on the
  48. @@ -44,25 +48,19 @@
  49.  do the trick:
  50.  
  51.  # put ourselves in the STAFF workgroup on the other subnet
  52. -192.0.3.255 STAFF S
  53. -
  54. -Notice the S at the end! It is very important you include this as this
  55. -entry without the S could cause a broadcast storm!
  56. +192.0.3.255 STAFF G
  57.  
  58. -If browsing is causing you trouble you can disable it with the -b
  59. -option to nmbd.
  60. +Notice the G at the end! It is very important you include this as this
  61. +entry without the G could cause a broadcast storm! 
  62.  
  63. -If something doesn't work then hopefully the log.nmb.debug file will
  64. -help you track down the problem.
  65. +If something doesn't work then hopefully the log.nmb file will
  66. +help you track down the problem. Try a debug level of 2 or 3 for
  67. +finding problems.
  68.  
  69.  Note that if it doesn't work for you, then you should still be able to
  70.  type the server name as \\SERVER in filemanager then hit enter and
  71.  filemanager should display the list of available shares.
  72.  
  73. -Remember: Samba can only participate in EXISTING workgroups. If you specify
  74. -a workgroup that dosn't exist then browsing won't work. In future versions
  75. -Samba will probably be able to create it's own workgroups.
  76. -
  77.  Some people find browsing fails because they don't have the global
  78.  "guest account" set to a valid account. Remember that the IPC$
  79.  connection that lists the shares is done as guest, and thus you must
  80. @@ -75,36 +73,34 @@
  81.  are now far more likely to correctly find your broadcast and network
  82.  addess, so in most cases these aren't needed.
  83.  
  84. -
  85. -FINDING A MASTER BROWSER
  86. -========================
  87. -
  88. -Often people find that nmbd has trouble finding a master browser. The
  89. -likely causes of this problem are:
  90. +The other big problem people have is that their broadcast address,
  91. +netmask or IP address is wrong (specified with the -B, -N and -I
  92. +options to nmbd). 
  93.  
  94. -1) you are using the wrong broadcast address
  95. -
  96. -2) You are using the wrong workgroup name
  97. -
  98. -3) You don't have a master browser.
  99. -
  100. -To find out which of the above problems applies to you use the -M
  101. -switch to nmbd to search for a master browser manually. eg:
  102. +FORCING SAMBA TO BE THE MASTER
  103. +==============================
  104.  
  105. -nmbd -M FOOGROUP -B a.b.c.d
  106. +Who becomes the "master browser" is determined by an election process
  107. +using broadcasts. Each election packet contains a number of parameters
  108. +which determine what precedence (bias) a host should have in the
  109. +election. By default Samba uses a very low precedence and thus loses
  110. +elections to just about anyone else.
  111. +
  112. +If you want Samba to win elections then just set the "os level" global
  113. +option in smb.conf to a higher number. It defaults to 0. Using 3 would
  114. +make it win all elections over every other system (except other samba
  115. +systems!) 
  116.  
  117. -This will look for a master browser for the workgroup FOOGROUP using
  118. -broadcast a.b.c.d. When you successfully find a master browser you
  119. -know you have the broadcast and group name right.
  120. +A "os level" of 2 would make it beat WfWg and Win95, but not NTAS.
  121.  
  122.  
  123.  NOTE ABOUT BROADCAST ADDRESSES
  124.  ==============================
  125.  
  126.  If your network uses a "0" based broadcast address (for example if it
  127. -ends in a 0) then you may strike problems. Windows for Workgroups does
  128. -not seem to support a 0's broadcast and you will probably find that
  129. -browsing and name lookups won't work.
  130. +ends in a 0) then you will strike problems. Windows for Workgroups
  131. +does not seem to support a 0's broadcast and you will probably find
  132. +that browsing and name lookups won't work.
  133.  
  134.  You have a few options:
  135.  
  136. @@ -112,7 +108,9 @@
  137.  .255 (check with your local network guru for details)
  138.  
  139.  2) set the nmbd broadcast to a 1's based address on the command line using
  140. -the -B option.
  141. +the -B option. This only works if your network setup listens on both
  142. +0s and 1s based broadcasts. The -B option can only control what
  143. +address it sends to, not what it listens on.
  144. +
  145.  
  146. -3) explicitly support both broadcasts with two entries in your lmhosts file.
  147.  
  148. diff -u -r --new-file last-version/docs/DIAGNOSIS.txt samba-1.9.15/docs/DIAGNOSIS.txt
  149. --- last-version/docs/DIAGNOSIS.txt    Sat Nov 11 14:19:09 1995
  150. +++ samba-1.9.15/docs/DIAGNOSIS.txt    Tue Nov 14 22:41:04 1995
  151. @@ -36,8 +36,8 @@
  152.   read only = yes
  153.  
  154.  
  155. -These tests also assume version 1.9.14 or later of the samba suite. If
  156. -you have version 1.9.13 then see "NOTE 1" below.
  157. +THESE TESTS ASSUME VERSION 1.9.15 OR LATER OF THE SAMBA SUITE. SOME
  158. +COMMANDS SHOWN DID NOT EXIST IN EARLIER VERSIONS
  159.  
  160.  
  161.  TEST 1:
  162. @@ -91,11 +91,8 @@
  163.  TEST 4:
  164.  -------
  165.  
  166. -run the command "nmbd -L __SAMBA__ -B BIGSERVER". You should get a
  167. -bunch of info back including the string "got a positive name query
  168. -response". You should also see a message "got a positive node status
  169. -response" and below that a list of netbios names. The name BIGSERVER
  170. -should be included in that list.
  171. +run the command "nmblookup -B BIGSERVER __SAMBA__". You should get the
  172. +IP address of your Samba server back.
  173.  
  174.  If you don't then nmbd is incorrectly installed. Check your inetd.conf
  175.  if yu run it from there, or that the daemon is running and listening
  176. @@ -109,40 +106,41 @@
  177.  TEST 5:
  178.  -------
  179.  
  180. -run the command "nmbd -L '*' -B ACLIENT"
  181. +run the command "nmblookup -B ACLIENT '*'"
  182.  
  183. -You should get a "positive name query response" from the PC. If you
  184. -don't then the client software on the PC isn't installed correctly, or
  185. -isn't started, or you got the name of the PC wrong. Note that you
  186. -probably won't get a "node status response" from the PC due to a bug
  187. -in the microsoft netbios nameserver implementation (it responds to the
  188. -wrong port number).
  189. +You should get the PCs IP address back. If you don't then the client
  190. +software on the PC isn't installed correctly, or isn't started, or you
  191. +got the name of the PC wrong. Note that you probably won't get a "node
  192. +status response" from the PC due to a bug in the microsoft netbios
  193. +nameserver implementation (it responds to the wrong port number).
  194.  
  195.  TEST 6:
  196.  -------
  197.  
  198. -run the command "nmbd -L '*'"
  199. +run the command "nmblookup -d 2 '*'"
  200.  
  201.  This time we are trying the same as the previous test but are trying
  202. -it via a broadcast to the default broadcast address. All Netbios/TCPIP
  203. -hosts on the network should respond, although Samba may not catch all
  204. -of the responses in the short time it listens.
  205. -
  206. -If this doesn't give a similar result to the previous test then nmbd
  207. -isn't correctly getting your broadcast address through its automatic
  208. -mechanism. In this case you should experiment with the -B option which
  209. -allows you to manually specify the broadcast address, overriding the
  210. -automatic detection. You should try different broadcast addresses
  211. -until your find the one that works. It will most likely be something
  212. -like a.b.c.255 as microsoft tcpip stacks only listen on 1's based
  213. -broadcast addresses. If you get stuck then ask your local networking
  214. -guru for help (and show them this paragraph).
  215. +it via a broadcast to the default broadcast address. A number of
  216. +Netbios/TCPIP hosts on the network should respond, although Samba may
  217. +not catch all of the responses in the short time it listens. You
  218. +should see "got a positive name query response" messages from several
  219. +hosts. 
  220. +
  221. +If this doesn't give a similar result to the previous test then
  222. +nmblookup isn't correctly getting your broadcast address through its
  223. +automatic mechanism. In this case you should experiment with the -B
  224. +option which allows you to manually specify the broadcast address,
  225. +overriding the automatic detection. You should try different broadcast
  226. +addresses until your find the one that works. It will most likely be
  227. +something like a.b.c.255 as microsoft tcpip stacks only listen on 1's
  228. +based broadcast addresses. If you get stuck then ask your local
  229. +networking guru for help (and show them this paragraph).
  230.  
  231.  If you find you do need the -B option (ie. the automatic detection
  232.  doesn't work) then you should add the -B option with the right
  233.  broadcast address for your network to the command line of nmbd in
  234.  inetd.conf or in the script you use to start nmbd as a daemon. Once
  235. -you do this go back to the "nmbd -L __SAMBA__ -B BIGSERVER" test to
  236. +you do this go back to the "nmblookup __SAMBA__ -B BIGSERVER" test to
  237.  make sure you have it running properly.
  238.  
  239.  If your PC and server aren't on the same subnet then you will need to
  240. @@ -152,16 +150,6 @@
  241.  TEST 7:
  242.  -------
  243.  
  244. -run the command "nmbd -M -" 
  245. -
  246. -this should find a master browser on your network. If you don't have
  247. -one then browsing won't work with samba. See the file BROWSING.txt for
  248. -details. Note that you may need the -B option to the command if the
  249. -previous test showed that the default broadcast is incorrect.
  250. -
  251. -TEST 8:
  252. --------
  253. -
  254.  run the command "smbclient '\\BIGSERVER\TMP'". You should then be
  255.  prompted for a password. You should use the password of the account
  256.  you are logged into the unix box with. If you want to test with
  257. @@ -187,7 +175,7 @@
  258.  when you type "dir".
  259.  
  260.  
  261. -TEST 9:
  262. +TEST 8:
  263.  -------
  264.  
  265.  On the PC type the command "net view \\BIGSERVER". You will need to do
  266. @@ -212,7 +200,7 @@
  267.  pages)
  268.  
  269.  
  270. -TEST 10:
  271. +TEST 9:
  272.  --------
  273.  
  274.  run the command "net use x: \\BIGSERVER\TMP". You should be prompted
  275. @@ -228,7 +216,7 @@
  276.  fixes things you may need the username mapping option.
  277.  
  278.  
  279. -TEST 11:
  280. +TEST 10:
  281.  --------
  282.  
  283.  From file manager try to browse the server. Your samba server should
  284. @@ -246,18 +234,4 @@
  285.  Try the mailing list or newsgroup, or use the tcpdump-smb utility to
  286.  sniff the problem.
  287.  
  288. -
  289. -ADDITIONAL NOTES
  290. -----------------
  291. -
  292. -NOTE 1: 
  293. -
  294. -If you have version 1.9.13 of Samba then the "nmbd -L ACLIENT -B
  295. -ACLIENT" test may fail if your client doesn't export any shares. To
  296. -fix this either export a share or change the "lookup_type" in
  297. -nameserv.c from ' ' to 0 and recompile.
  298. -
  299. -Also the "wildcard" lookup capability used in the command "nmbd -L
  300. -'*'" was only added in 1.9.14. If you have 1.9.13 then use a clients
  301. -netbios name instead (for example "nmbd -L ACLIENT").
  302.  
  303. diff -u -r --new-file last-version/docs/HINTS.txt samba-1.9.15/docs/HINTS.txt
  304. --- last-version/docs/HINTS.txt    Wed Apr 26 16:36:44 1995
  305. +++ samba-1.9.15/docs/HINTS.txt    Tue Nov 14 22:41:54 1995
  306. @@ -124,19 +124,6 @@
  307.  
  308.  Often WfWg will totally ignore a password you give it in a dialog box.
  309.  
  310. -
  311. ------------------------
  312. -HINT: Getting WfWg to be a master browser
  313. -
  314. -Apart from exporting a drive, you should be able to get WfWg to be a
  315. -master browser by using:
  316. -
  317. -[Network]
  318. -MaintainServerList=YES
  319. -
  320. -in the system.ini file
  321. -
  322. -
  323.  ----------------------
  324.  HINT: Using MS Access
  325.  
  326. diff -u -r --new-file last-version/docs/INSTALL.txt samba-1.9.15/docs/INSTALL.txt
  327. --- last-version/docs/INSTALL.txt    Fri Jul  7 08:30:27 1995
  328. +++ samba-1.9.15/docs/INSTALL.txt    Tue Nov 14 22:55:40 1995
  329. @@ -50,11 +50,14 @@
  330.  The simplest useful configuration file would be something like this:
  331.  
  332.  [homes]
  333. +    workgroup = MYGROUP
  334.      guest ok = no
  335.      read only = no
  336.  
  337.  which would allow connections by anyone with an account on the server,
  338. -using either their login name or "homes" as the service name.
  339. +using either their login name or "homes" as the service name. (Note
  340. +that I also set the workgroup that Samba is part of. See BROWSING.txt
  341. +for defails)
  342.  
  343.  Note that "make install" will not install a smb.conf file. You need to
  344.  create it yourself. You will also need to create the path you specify
  345. @@ -147,7 +150,7 @@
  346.  also be used to see what shares are available on other LanManager
  347.  clients (such as WfWg).
  348.  
  349. -If you chose user level security then you may find that Samba requests
  350. +If you choose user level security then you may find that Samba requests
  351.  a password before it will list the shares. See the smbclient docs for
  352.  details. (you can force it to list the shares without a password by
  353.  adding the option -U% to the command line. This will not work with
  354. @@ -199,72 +202,21 @@
  355.  documentation (or source code) so that the next person will find it
  356.  easier. 
  357.  
  358. +DIAGNOSING PROBLEMS
  359. +===================
  360.  
  361. -TESTING NMBD
  362. -============
  363. +If you have instalation problems then go to DIAGNOSIS.txt to try to
  364. +find the problem.
  365.  
  366. -As of version 1.7.00 it is possible to test nmbd to see if it is
  367. -correctly installed. This can also test to see if it can auto-detect
  368. -your broadcast address.
  369. -
  370. -Under some operating systems you can only test the broadcast part if
  371. -running as root. You can test other functionality from a non-root
  372. -account. To test from root use:
  373. -
  374. -nmbd -L TESTNAME
  375. -
  376. -where TESTNAME is the netbios name you wish to test. This would
  377. -typically be the hostname of the unix host where you installed nmbd.
  378. -It should return the IP address of the host you are looking for. If it
  379. -doesn't then something is wrong with your nmbd configuration. (It is
  380. -also possibe that you have a net configuration that doesn't send
  381. -broadcasts to itself. Some Linux configurations do this.)
  382. -
  383. -If it fails then it could mean it is not correctly detecting your
  384. -broadcast address or netmask. You will then need to supply the -B and
  385. --N parameters. See the nmbd man page for details.
  386. -
  387. -It has succeeded if somewhere in the output is a line like:
  388. -
  389. -ww.xx.yy.zz HOSTNAME
  390. -
  391. -which means it managed to look the IP correctly.
  392. -
  393. -To test from a non-root account use:
  394. -
  395. -nmbd -B HOSTNAME -L TESTNAME
  396. -
  397. -where hostname is the host name of the host where nmbd is installed
  398. -and TESTNAME is the name you want to test. Typically this would be the
  399. -same as HOSTNAME.
  400. -
  401. -
  402. -NAME RESOLUTION
  403. -===============
  404. -
  405. -Probably the most common problem people have when installing Samba is
  406. -getting name resolution to work. This is usually caused by incorrect
  407. -settings for nmbd.
  408. -
  409. -One solution is to use nmbd as a WINS server, instead of using name
  410. -resolution by broadcast. To do this you need to enter the IP address
  411. -of the Samba server in the WINS section of your WfWg, Win95 or WinNT TCP/IP
  412. -setup.
  413. -
  414. -As a last resort you can use a lmhosts file on the PC to resolve names,
  415. -as long as you enable lmhosts name resolution in the right dialog
  416. -box. This doesn't lend itself very well to update, however.
  417. -
  418. -The best solution is, however, to fix the nmbd setup. Experimentation
  419. -and careful reading of the Samba docs should help.
  420. -
  421.  SCOPE IDs
  422.  =========
  423.  
  424.  By default Samba uses a blank scope ID. This means all your windows
  425.  boxes must also have a blank scope ID. If you really want to use a
  426.  non-blank scope ID then you will need to use the -i <scope> option to
  427. -nmbd, smbd, and smbclient.
  428. +nmbd, smbd, and smbclient. All your PCs will need to have the same
  429. +setting for this to work. I do not recommend scope IDs.
  430. +
  431.  
  432.  CHOOSING THE PROTOCOL LEVEL
  433.  ===========================
  434. @@ -350,9 +302,9 @@
  435.  DENY_NONE, DENY_READ, DENY_WRITE or DENY_ALL. There are also special
  436.  compatability modes called DENY_FCB and DENY_DOS.
  437.  
  438. -By default Samba does not implement these share modes. If you use
  439. -"share modes = yes" then Samba will implement them using locking files
  440. -in the "lock directory". See the man pages for details.
  441. +You can disable share modes using "share modes = no". This may be
  442. +useful on a heavily loaded server as the share modes code is very
  443. +slow. 
  444.  
  445.  
  446.  MAPPING USERNAMES
  447. diff -u -r --new-file last-version/docs/MIRRORS samba-1.9.15/docs/MIRRORS
  448. --- last-version/docs/MIRRORS    Fri Sep 15 19:02:39 1995
  449. +++ samba-1.9.15/docs/MIRRORS    Mon Nov 13 08:31:20 1995
  450. @@ -8,7 +8,7 @@
  451.  ftp://sunsite.unc.edu/pub/Linux/system/Network/Samba/
  452.  ftp://ftp.choc.apana.org.au/pub/samba
  453.  ftp://ftp.uni-trier.de/pub/unix/network/samba/
  454. -
  455. +ftp://ftp.spectrum.titan.com/pub/samba
  456.  
  457.  There are several others. Give archie a try.
  458.  
  459. diff -u -r --new-file last-version/docs/nmbd.8 samba-1.9.15/docs/nmbd.8
  460. --- last-version/docs/nmbd.8    Mon Apr 17 18:27:52 1995
  461. +++ samba-1.9.15/docs/nmbd.8    Tue Nov 14 22:33:04 1995
  462. @@ -20,23 +20,9 @@
  463.  .B -H
  464.  .I netbios hosts file
  465.  ] [
  466. -.B -L
  467. -.I netbios name
  468. -] [
  469. -.B -M
  470. -.I workgroup name
  471. -] [
  472.  .B -N
  473.  .I netmask
  474.  ] [
  475. -.B -P
  476. -] [
  477. -.B -R
  478. -] [
  479. -.B -b
  480. -] [
  481. -.B -S
  482. -] [
  483.  .B -d
  484.  .I debuglevel
  485.  ] [
  486. @@ -46,22 +32,17 @@
  487.  .B -n
  488.  .I netbios name
  489.  ] [
  490. -.B -O
  491. -.I socket options
  492. -] [
  493.  .B -p
  494.  .I port number
  495. -] [
  496. -.B -T
  497. -.I browse interval
  498.  ]
  499. +
  500.  .SH DESCRIPTION
  501.  This program is part of the Samba suite.
  502.  
  503.  .B nmbd
  504.  is a server that understands and can reply to netbios
  505.  name service requests, like those produced by LanManager
  506. -clients. 
  507. +clients. It also controls browsing.
  508.  
  509.  LanManager clients, when they start up, may wish to locate a LanManager server.
  510.  That is, they wish to know what IP number a specified host is using.
  511. @@ -82,11 +63,6 @@
  512.  means is that it will respond to all name requests that it receives
  513.  that are not broadcasts, as long as it can resolve the name.
  514.  .SH OPTIONS
  515. -.B -b
  516. -
  517. -.RS 3
  518. -This toggles support for browsing from WfWg. It defaults to on.
  519. -.RE
  520.  .B -B
  521.  
  522.  .RS 3
  523. @@ -172,7 +148,7 @@
  524.  from the -G option) are registered on the network (unless the -R
  525.  option has been selected).
  526.  
  527. -A S means that the specified address is a broadcast address of a
  528. +A S or G means that the specified address is a broadcast address of a
  529.  network that you want people to be able to browse you from. Nmbd will
  530.  search for a master browser in that domain and will send host
  531.  announcements to that machine, informing it that the specifed somain
  532. @@ -209,7 +185,7 @@
  533.  
  534.          # now we want another subnet to be able to browse
  535.          # us in the workgroup UNIXSERV
  536. -        192.0.2.255  UNIXSERV S
  537. +        192.0.2.255  UNIXSERV G
  538.  
  539.  .RE
  540.  
  541. @@ -229,33 +205,6 @@
  542.  as a daemon or in inetd.
  543.  
  544.  .RE
  545. -.B -L
  546. -.I netbios name
  547. -
  548. -.RS 3
  549. -If this parameter is given, the server will look up the specified
  550. -.I netbios name,
  551. -report success or failure, then exit. If successful, the IP address of the
  552. -name located will be reported. This is useful for determining whether
  553. -a netbios name is in use on a subnet and for matching IP addresses to netbios
  554. -names.
  555. -
  556. -This option is meant to be used interactively on the command line, not
  557. -as a daemon or in inetd.
  558. -
  559. -Use of this parameter causes options 
  560. -.B -D
  561. -,
  562. -.B -P
  563. -,
  564. -.B -R
  565. -and
  566. -.B -n
  567. -to be ignored.
  568. -
  569. -By default, the server will NOT do this.
  570. -.RE
  571. -
  572.  .B -N
  573.  
  574.  .RS 3
  575. @@ -272,28 +221,6 @@
  576.  number.
  577.  .RE
  578.  
  579. -.B -P
  580. -
  581. -.RS 3
  582. -If specified, this parameter causes the server to operate passively. That is,
  583. -it continues to field requests, but will not respond.
  584. -
  585. -By default, the server will NOT operate passively.
  586. -.RE
  587. -
  588. -.B -S
  589. -
  590. -.RS 3
  591. -If specified, this parameter causes the server to respond to broadcast
  592. -name queries for hosts that can be found with the gethostbyname() call
  593. -(which normally goes to NIS or DNS). It will NOT respond if the host
  594. -being queried is on the same subnet as the server. This is useful so
  595. -clients can connect to servers to which they cannot broadcast.
  596. -
  597. -By default, the server will NOT respond to any broadcast queries other
  598. -than it's own name.
  599. -.RE
  600. -
  601.  .B -d
  602.  .I debuglevel
  603.  .RS 3
  604. @@ -351,13 +278,6 @@
  605.  name of the host on which the server is running.
  606.  .RE
  607.  
  608. -.B -O
  609. -.I socket options
  610. -.RS 3
  611. -
  612. -See the socket options section of smb.conf(5) for details
  613. -
  614. -.RE
  615.  .B -p
  616.  .I port number
  617.  .RS 3
  618. @@ -377,13 +297,6 @@
  619.  
  620.  This parameter is not normally specified except in the above situation.
  621.  .RE
  622. -.B -T
  623. -.I browse interval
  624. -.RS 3
  625. -
  626. -This sets the number of seconds between browse announcements. It
  627. -defaults to 60 seconds. The minimum value is 10 seconds.
  628. -
  629.  .SH FILES
  630.  
  631.  .B /etc/inetd.conf
  632. diff -u -r --new-file last-version/docs/smb.conf.5 samba-1.9.15/docs/smb.conf.5
  633. --- last-version/docs/smb.conf.5    Sun Nov  5 11:35:38 1995
  634. +++ samba-1.9.15/docs/smb.conf.5    Tue Nov 14 22:47:42 1995
  635. @@ -366,6 +366,8 @@
  636.  
  637.  null passwords
  638.  
  639. +os level
  640. +
  641.  packet size
  642.  
  643.  passwd chat
  644. @@ -376,6 +378,8 @@
  645.  
  646.  password server
  647.  
  648. +preferred master
  649. +
  650.  preload
  651.  
  652.  printing
  653. @@ -1492,6 +1496,10 @@
  654.  .B Example:
  655.      null passwords = yes
  656.  
  657. +.SS os level (G)
  658. +This integer value controls what level Samba advertises itself as for
  659. +browse elections. See BROWSING.txt for details.
  660. +
  661.  .SS packet size (G)
  662.  The maximum transmit packet size during a raw read. This option is no
  663.  longer implemented as of version 1.7.00, and is kept only so old
  664. @@ -1693,6 +1701,13 @@
  665.  .B Example:
  666.      preexec = echo \"%u connected to %S from %m (%I)\" >> /tmp/log
  667.  
  668. +.SS preferred master (G)
  669. +This boolean parameter controls if Samba is a preferred master browser
  670. +for its workgroup. Setting this gives it a slight edge in elections
  671. +and also means it will automatically start an election when it starts
  672. +up. 
  673. +
  674. +It is on by default.
  675.  
  676.  .SS preload
  677.  This is an alias for "auto services"
  678. diff -u -r --new-file last-version/source/Makefile samba-1.9.15/source/Makefile
  679. --- last-version/source/Makefile    Sun Nov 12 12:56:19 1995
  680. +++ samba-1.9.15/source/Makefile    Tue Nov 14 21:28:52 1995
  681. @@ -425,7 +425,7 @@
  682.  LIBS = $(LIBS1) $(LIBSM) $(DCE_LIBS) $(DES_LIB)
  683.  
  684.  PROGS1 = smbd smbclient nmbd testparm testprns smbrun smbstatus smbpasswd 
  685. -PROGS = $(PROGS1) nmbd2 nmblookup
  686. +PROGS = $(PROGS1) nmblookup
  687.  SCRIPTS = smbtar
  688.  
  689.  all : CHECK $(PROGS)
  690. @@ -462,17 +462,13 @@
  691.      @echo Linking smbrun
  692.      @$(CC) $(CFLAGS) -o smbrun smbrun.o $(LIBS)
  693.  
  694. -nmbd: nameserv.o $(UTILOBJ)  
  695. -    @echo Linking nmbd
  696. -    @$(CC) $(CFLAGS) -o nmbd nameserv.o $(UTILOBJ) $(LIBS)
  697. -
  698.  nmblookup: nmblookup.o $(UTILOBJ)  
  699.      @echo Linking nmblookup
  700.      @$(CC) $(CFLAGS) -o nmblookup nmblookup.o nmblib.o $(UTILOBJ) $(LIBS)
  701.  
  702. -nmbd2: nameserv2.o nmblib.o $(UTILOBJ) 
  703. -    @echo Linking nmbd2
  704. -    @$(CC) $(CFLAGS) -o nmbd2 nameserv2.o nmblib.o $(PARAMOBJ) $(LIBS)
  705. +nmbd: nameserv.o nmblib.o $(UTILOBJ) 
  706. +    @echo Linking nmbd
  707. +    @$(CC) $(CFLAGS) -o nmbd nameserv.o nmblib.o $(PARAMOBJ) $(LIBS)
  708.  
  709.  smbclient: client.o clitar.o getsmbpass.o $(UTILOBJ) 
  710.      @echo Linking smbclient
  711. diff -u -r --new-file last-version/source/change-log samba-1.9.15/source/change-log
  712. --- last-version/source/change-log    Sun Nov 12 21:41:40 1995
  713. +++ samba-1.9.15/source/change-log    Tue Nov 14 23:17:02 1995
  714. @@ -1591,7 +1591,7 @@
  715.      - added force_user to conn struct
  716.  
  717.  
  718. -2.0.0:
  719. +1.9.15: 14/11/95
  720.          - removed bcast override from workgroup announce in nmbd
  721.      - aix patch, added NO_SYSMOUNTH, from 
  722.      lionel leston <102624.346@compuserve.com>    
  723. @@ -1645,11 +1645,30 @@
  724.      - added browse mastering code
  725.      - started integration with smb.conf for nmbd2
  726.      - released p5
  727. +    - fixed death_time (should be t+ttl*3)
  728. +    - fixed non-removal of dead servers
  729. +    - added smbstatus -u patch from oskarh@spornet.is (Oskar Hannesson)
  730. +    - NETGROUP fix from J.W.Schilperoort@research.kpn.com
  731. +    - select and NO_SETGROUPS patches from lennylim@netcom.com (Lenny
  732. +    Lim)
  733. +    - added LINKS_READ_ONLY define in dos_mode() for LM/X
  734. +    compatability
  735. +    - "dir a.c" bug fixed thanks to roderich@nodebonn.muc.bmw.de 
  736. +    (Roderich Schupp)
  737. +    - job cancel fix in client from peo@mtek.chalmers.se
  738. +    - changed nmbd2 to nmbd 
  739. +    - fixed "dir a*" under trans2 lookups
  740. +    - added StrnCaseCmp()
  741. +    - updated docs a bit for new browsing stuff
  742. +    - updated INSTALL.txt
  743. +    - hopefully fixed server level security with WfWg
  744.  
  745.  
  746.  ==========
  747.  todo:
  748.  
  749. +dup/close 0 for getopt?
  750. +
  751.  implement SMBmove and SMBcopy ??
  752.  
  753.  add option to print more info about locked files (full path, share name
  754. @@ -1659,8 +1678,6 @@
  755.  
  756.  no refresh/reg of new IP? or send wack and challenge owner?
  757.  
  758. -new nmb.conf file
  759. -
  760.  protocol drop back in client to avoid openX etc.
  761.  
  762.  very slow listing CD, perhaps because of order of stat and readdir?
  763. @@ -1688,4 +1705,10 @@
  764.  ALLOW_PASSWORD_CHANGE only compiles/works on some systems
  765.  
  766.  weird foooooooo/open.exe bug on NT
  767. +
  768. +
  769. +lpd stuff:
  770. + Tony Aiuto  (tony@ics.com)
  771. +
  772. +
  773.  
  774. diff -u -r --new-file last-version/source/client.c samba-1.9.15/source/client.c
  775. --- last-version/source/client.c    Sat Nov 11 15:23:12 1995
  776. +++ samba-1.9.15/source/client.c    Tue Nov 14 21:54:30 1995
  777. @@ -615,7 +615,7 @@
  778.  {
  779.  
  780.    if (!((finfo->mode & aDIR) == 0 && *fileselection && 
  781. -    !mask_match(finfo->name,fileselection,False,True)) &&
  782. +    !mask_match(finfo->name,fileselection,False,False)) &&
  783.        !(recurse_dir && (strequal(finfo->name,".") || 
  784.              strequal(finfo->name,".."))))
  785.      {
  786. @@ -2155,7 +2155,7 @@
  787.    p = skip_string(p,1);
  788.    strcpy(p,"");
  789.    p = skip_string(p,1);
  790. -  SSVAL(p,0,0);            /* level 0 */
  791. +  SSVAL(p,0,job);     
  792.    p += 2;
  793.  
  794.    if (call_api(PTR_DIFF(p,param),0,
  795. diff -u -r --new-file last-version/source/includes.h samba-1.9.15/source/includes.h
  796. --- last-version/source/includes.h    Sun Nov 12 12:31:47 1995
  797. +++ samba-1.9.15/source/includes.h    Tue Nov 14 22:10:06 1995
  798. @@ -762,6 +762,9 @@
  799.  #define getpass(s) getsmbpass(s)
  800.  #endif
  801.  
  802. +#ifndef FD_SETSIZE
  803. +#define FD_SETSIZE 255
  804. +#endif
  805.  
  806.  #ifndef MAXINT
  807.  #define MAXINT ((((unsigned)1)<<(sizeof(int)*8-1))-1)
  808. @@ -969,6 +972,7 @@
  809.  
  810.  #ifdef NOSTRCASECMP
  811.  #define strcasecmp(s1,s2) StrCaseCmp(s1,s2)
  812. +#define strncasecmp(s1,s2,n) StrnCaseCmp(s1,s2,n)
  813.  #endif
  814.  
  815.  #ifndef strcpy
  816. diff -u -r --new-file last-version/source/loadparm.c samba-1.9.15/source/loadparm.c
  817. --- last-version/source/loadparm.c    Sun Nov 12 13:12:57 1995
  818. +++ samba-1.9.15/source/loadparm.c    Wed Nov 15 00:05:39 1995
  819. @@ -142,6 +142,8 @@
  820.     int printing;
  821.     int maxdisksize;
  822.     int lpqcachetime;
  823. +   int os_level;
  824. +   BOOL bPreferredMaster;
  825.     BOOL bEncryptPasswords;
  826.     BOOL bStripDot;
  827.     BOOL bNullPasswords;
  828. @@ -388,6 +390,8 @@
  829.  #ifdef KANJI
  830.    {"coding system",    P_INTEGER, P_GLOBAL, &coding_system, handle_coding_system},
  831.  #endif /* KANJI */
  832. +  {"os level",         P_INTEGER, P_GLOBAL, &Globals.os_level,          NULL},
  833. +  {"preferred master", P_BOOL,    P_GLOBAL, &Globals.bPreferredMaster,  NULL},
  834.  
  835.    {"-valid",           P_BOOL,    P_LOCAL,  &sDefault.valid,            NULL},
  836.    {"comment",          P_STRING,  P_LOCAL,  &sDefault.comment,          NULL},
  837. @@ -529,6 +533,9 @@
  838.    Globals.bReadbmpx = True;
  839.    Globals.bNullPasswords = False;
  840.    Globals.bStripDot = False;
  841. +  Globals.os_level = 0;
  842. +  Globals.bPreferredMaster = True;
  843. +
  844.  #ifdef KANJI
  845.    coding_system = interpret_coding_system (KANJI, SJIS_CODE);
  846.  #endif /* KANJI */
  847. @@ -636,6 +643,7 @@
  848.  FN_GLOBAL_STRING(lp_username_map,&Globals.szUsernameMap)
  849.  FN_GLOBAL_STRING(lp_character_set,&Globals.szCharacterSet) 
  850.  
  851. +FN_GLOBAL_BOOL(lp_preferred_master,&Globals.bPreferredMaster)
  852.  FN_GLOBAL_BOOL(lp_load_printers,&Globals.bLoadPrinters)
  853.  FN_GLOBAL_BOOL(lp_use_rhosts,&Globals.bUseRhosts)
  854.  FN_GLOBAL_BOOL(lp_getwdcache,&use_getwd_cache)
  855. @@ -648,6 +656,7 @@
  856.  FN_GLOBAL_BOOL(lp_encrypted_passwords,&Globals.bEncryptPasswords)
  857.  
  858.  
  859. +FN_GLOBAL_INTEGER(lp_os_level,&Globals.os_level)
  860.  FN_GLOBAL_INTEGER(lp_max_log_size,&Globals.max_log_size)
  861.  FN_GLOBAL_INTEGER(lp_mangledstack,&Globals.mangled_stack)
  862.  FN_GLOBAL_INTEGER(lp_maxxmit,&Globals.max_xmit)
  863. @@ -834,7 +843,7 @@
  864.        sprintf(comment,"Home directory of %s",pszHomename);
  865.        string_set(&iSERVICE(i).comment,comment);
  866.      }
  867. -  iSERVICE(i).bAvailable = True;
  868. +  iSERVICE(i).bAvailable = sDefault.bAvailable;
  869.    iSERVICE(i).bBrowseable = sDefault.bBrowseable;
  870.  
  871.    DEBUG(3,("adding home directory %s at %s\n", pszHomename, pszHomedir));
  872. diff -u -r --new-file last-version/source/loadparm.h samba-1.9.15/source/loadparm.h
  873. --- last-version/source/loadparm.h    Sun Nov 12 13:08:34 1995
  874. +++ samba-1.9.15/source/loadparm.h    Tue Nov 14 20:59:30 1995
  875. @@ -56,10 +56,12 @@
  876.  extern char *lp_magicscript(int iService);
  877.  extern char *lp_magicoutput(int iService);
  878.  extern char *lp_mangled_map(int iService);
  879. +extern int  lp_os_level(void);
  880.  extern int  lp_max_log_size(void);
  881.  extern int  lp_maxxmit(void);
  882.  extern int  lp_maxmux(void);
  883.  extern int  lp_mangledstack(void);
  884. +extern BOOL lp_preferred_master(void);
  885.  extern BOOL lp_getwdcache(void);
  886.  extern BOOL lp_use_rhosts(void);
  887.  extern BOOL lp_readprediction(void);
  888. diff -u -r --new-file last-version/source/nameserv.c samba-1.9.15/source/nameserv.c
  889. --- last-version/source/nameserv.c    Sun Nov 12 12:08:18 1995
  890. +++ samba-1.9.15/source/nameserv.c    Tue Nov 14 21:40:25 1995
  891. @@ -1,7 +1,7 @@
  892.  /* 
  893.     Unix SMB/Netbios implementation.
  894.     Version 1.9.
  895. -   NBT netbios routines and daemon
  896. +   NBT netbios routines and daemon - version 2
  897.     Copyright (C) Andrew Tridgell 1994-1995
  898.     
  899.     This program is free software; you can redistribute it and/or modify
  900. @@ -17,83 +17,94 @@
  901.     You should have received a copy of the GNU General Public License
  902.     along with this program; if not, write to the Free Software
  903.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  904. +   
  905.  */
  906.  
  907.  #include "includes.h"
  908. +#include "loadparm.h"
  909. +#include "nameserv.h"
  910.  
  911. -extern pstring debugf;
  912. +
  913. +static void queue_packet(struct packet_struct *packet);
  914. +void process(void);
  915. +static void dump_names(void);
  916. +static void announce_request(char *group);
  917. +
  918.  extern int DEBUGLEVEL;
  919.  
  920. -extern pstring scope;
  921. +extern pstring debugf;
  922. +pstring servicesf = CONFIGFILE;
  923.  
  924. -static int browse_interval = BROWSE_INTERVAL;
  925. +extern pstring scope;
  926.  
  927. -BOOL browse = True;
  928. -BOOL dns_serve = False;
  929. +extern BOOL CanRecurse;
  930.  
  931. -extern struct in_addr lastip;
  932. -extern int lastport;
  933.  extern struct in_addr myip;
  934.  extern struct in_addr bcast_ip;
  935.  extern struct in_addr Netmask;
  936.  extern pstring myhostname;
  937.  static pstring host_file;
  938.  static pstring myname="";
  939. -static int num_good_sends=0;
  940. -static int num_good_receives=0;
  941. -static pstring lookup="";
  942. -static int Client138=-1;
  943. -enum name_sources {LMHOSTS, REGISTER, SELF, DNS};
  944. -
  945. -/* this is the structure used for the local netbios name table */
  946. -typedef struct
  947. -{
  948. -  time_t start_time;
  949. -  int ttl;
  950. -  struct in_addr ip;
  951. -  struct in_addr master_ip;
  952. -  BOOL found_master;
  953. -  BOOL valid;
  954. -  BOOL isgroup;
  955. -  BOOL unicast;
  956. -  char name[100];
  957. -  int type;
  958. -  int count;  
  959. -  enum name_sources source;
  960. -} name_struct;
  961.  
  962. +static int ClientNMB=-1;
  963. +static int ClientDGRAM=-1;
  964.  
  965. -static int num_names=0;
  966. -static name_struct *names = NULL;
  967. +static BOOL needannounce=True;
  968.  
  969. -extern int Client;
  970. +/* this is our name database */
  971. +static struct name_record *namelist = NULL;
  972.  
  973. -#define NAMEVALID(i) names[i].valid
  974. -#define ISGROUP(i) (names[i].isgroup)
  975. +/* list of servers to be returned by NetServerEnum */
  976. +static struct server_record *serverlist = NULL;
  977.  
  978. -void process(void);
  979. +/* this is the domain list. For the moment we will assume that our
  980. +   primary domain is the first one listed in this list */
  981. +static struct domain_record *domainlist = NULL;
  982.  
  983.  /* are we running as a daemon ? */
  984.  static BOOL is_daemon = False;
  985.  
  986. -/* machine comment */
  987. -static pstring comment="";
  988. +/* machine comment for host announcements */
  989. +static pstring ServerComment="";
  990. +
  991. +static BOOL got_bcast = False;
  992. +static BOOL got_myip = False;
  993. +static BOOL got_nmask = False;
  994.  
  995. -/* die after this number of 10ths of seconds if no activity and not a daemon */
  996. -static int idle_timeout = NMBD_INETD_TIMEOUT*1000;
  997. +static BOOL updatedlists = False;
  998. +static int  updatecount=0;
  999.  
  1000. -extern pstring user_socket_options;
  1001. +/* what server type are we currently */
  1002. +static int ServerType = 
  1003. +SV_TYPE_WORKSTATION | SV_TYPE_SERVER | SV_TYPE_TIME_SOURCE |
  1004. +SV_TYPE_PRINTQ_SERVER | SV_TYPE_SERVER_UNIX | SV_TYPE_POTENTIAL_BROWSER;
  1005.  
  1006. -static void add_group_name(char *name);
  1007. -static void add_host_name(char *name,int type,struct in_addr *ip);
  1008. -static void dump_names(void);
  1009. +/* here are my election parameters */
  1010.  
  1011. +/* NTAS uses 2, NT uses 1, WfWg uses 0 */
  1012. +#define MAINTAIN_LIST 1
  1013. +#define ELECTION_VERSION 1
  1014.  
  1015. -static BOOL got_bcast = False;
  1016. -static BOOL got_myip = False;
  1017. -static BOOL got_nmask = False;
  1018. +static BOOL RunningElection = False;
  1019. +static BOOL needelection = False;
  1020. +static int ElectionCount = 0;
  1021. +static int StartupTime =0;
  1022.  
  1023.  
  1024. +/* WfWg uses 01040b01 */
  1025. +/* Win95 uses 01041501 */
  1026. +/* NTAS uses ?? */
  1027. +static uint32 ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
  1028. +
  1029. +/* we currently support being the master for just one group. Being the
  1030. +   master for more than one group might be tricky as NetServerEnum is
  1031. +   often asked for a list without naming the group */
  1032. +static fstring PrimaryGroup="";
  1033. +
  1034. +#define AM_MASTER (PrimaryGroup[0] && (ServerType & SV_TYPE_MASTER_BROWSER))
  1035. +
  1036. +#define MSBROWSE "\001\002__MSBROWSE__\002"
  1037. +
  1038.  /****************************************************************************
  1039.  catch a sighup
  1040.  ****************************************************************************/
  1041. @@ -101,10 +112,9 @@
  1042.  {
  1043.    BlockSignals(True);
  1044.  
  1045. -  DEBUG(0,("Got SIGHUP - not implemented\n"));
  1046. +  DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
  1047.    dump_names();
  1048. -  if (!is_daemon)
  1049. -    exit(1);
  1050. +  reload_services(True);
  1051.  
  1052.    BlockSignals(False);
  1053.  #ifndef DONT_REINSTALL_SIG
  1054. @@ -127,6 +137,43 @@
  1055.    return(0);
  1056.  }
  1057.  
  1058. +#if DUMP_CORE
  1059. +/*******************************************************************
  1060. +prepare to dump a core file - carefully!
  1061. +********************************************************************/
  1062. +static BOOL dump_core(void)
  1063. +{
  1064. +  char *p;
  1065. +  pstring dname;
  1066. +  strcpy(dname,debugf);
  1067. +  if ((p=strrchr(dname,'/'))) *p=0;
  1068. +  strcat(dname,"/corefiles");
  1069. +  mkdir(dname,0700);
  1070. +  chown(dname,getuid(),getgid());
  1071. +  chmod(dname,0700);
  1072. +  if (chdir(dname)) return(False);
  1073. +  umask(~(0700));
  1074. +
  1075. +#ifndef NO_GETRLIMIT
  1076. +#ifdef RLIMIT_CORE
  1077. +  {
  1078. +    struct rlimit rlp;
  1079. +    getrlimit(RLIMIT_CORE, &rlp);
  1080. +    rlp.rlim_cur = MAX(4*1024*1024,rlp.rlim_cur);
  1081. +    setrlimit(RLIMIT_CORE, &rlp);
  1082. +    getrlimit(RLIMIT_CORE, &rlp);
  1083. +    DEBUG(3,("Core limits now %d %d\n",rlp.rlim_cur,rlp.rlim_max));
  1084. +  }
  1085. +#endif
  1086. +#endif
  1087. +
  1088. +
  1089. +  DEBUG(0,("Dumping core in %s\n",dname));
  1090. +  return(True);
  1091. +}
  1092. +#endif
  1093. +
  1094. +
  1095.  /****************************************************************************
  1096.  possibly continue after a fault
  1097.  ****************************************************************************/
  1098. @@ -139,1536 +186,1585 @@
  1099.    if (is_daemon && errcount<100)
  1100.      process();
  1101.  
  1102. -  exit(1);
  1103. +#if DUMP_CORE
  1104. +    if (dump_core()) return;
  1105. +#endif
  1106. +
  1107. +  return;
  1108.  }
  1109.  
  1110.  /****************************************************************************
  1111.    true if two netbios names are equal
  1112.  ****************************************************************************/
  1113. -static BOOL name_equal(char *s1,char *s2,int type1,int type2)
  1114. +static BOOL name_equal(struct nmb_name *n1,struct nmb_name *n2)
  1115.  {
  1116. -  char n1[20],n2[20];
  1117. +  if (n1->name_type != n2->name_type) return(False);
  1118. +
  1119. +  return(strequal(n1->name,n2->name) && strequal(n1->scope,n2->scope));
  1120. +}
  1121.  
  1122. -  if (type1 != type2) return(False);
  1123. +/****************************************************************************
  1124. +  add a netbios name into the namelist
  1125. +  **************************************************************************/
  1126. +static void add_name(struct name_record *n)
  1127. +{
  1128. +  struct name_record *n2;
  1129.  
  1130. -  StrnCpy(n1,s1,15);
  1131. -  StrnCpy(n2,s2,15);
  1132. +  if (!namelist) {
  1133. +    namelist = n;
  1134. +    n->prev = NULL;
  1135. +    n->next = NULL;
  1136. +    return;
  1137. +  }
  1138.  
  1139. -  trim_string(n1,NULL," ");
  1140. -  trim_string(n2,NULL," ");
  1141. +  for (n2 = namelist; n2->next; n2 = n2->next) ;
  1142.  
  1143. -  return(strequal(n1,n2));
  1144. +  n2->next = n;
  1145. +  n->next = NULL;
  1146. +  n->prev = n2;
  1147.  }
  1148.  
  1149.  /****************************************************************************
  1150. -add a netbios name
  1151. -****************************************************************************/
  1152. -static int add_name(void)
  1153. +  add a domain into the list
  1154. +  **************************************************************************/
  1155. +static void add_domain(struct domain_record *d)
  1156.  {
  1157. -  int i;
  1158. +  struct domain_record *d2;
  1159.  
  1160. -  for (i=0;i<num_names;i++)
  1161. -    if (!names[i].valid)
  1162. -      break;
  1163. -
  1164. -  if (i==num_names) {
  1165. -    name_struct *n;
  1166. -    if (num_names == 0)    
  1167. -      n = (name_struct *)malloc(sizeof(name_struct));
  1168. -    else
  1169. -      n = (name_struct *)realloc(names,sizeof(name_struct)*(num_names+1));
  1170. -    if (!n) {
  1171. -      DEBUG(0,("Can't malloc more names space!\n"));
  1172. -      return(-1);
  1173. -    }
  1174. -    i = num_names;
  1175. -    num_names++;
  1176. -    names = n;
  1177. +  if (!domainlist) {
  1178. +    domainlist = d;
  1179. +    d->prev = NULL;
  1180. +    d->next = NULL;
  1181. +    return;
  1182.    }
  1183.  
  1184. -  bzero(&names[i],sizeof(names[i]));
  1185. +  for (d2 = domainlist; d2->next; d2 = d2->next) ;
  1186.  
  1187. -  return(i);
  1188. +  d2->next = d;
  1189. +  d->next = NULL;
  1190. +  d->prev = d2;
  1191.  }
  1192.  
  1193. +
  1194.  /****************************************************************************
  1195. -find a name
  1196. -****************************************************************************/
  1197. -static int find_name(char *s,int type,BOOL groups)
  1198. +  add a server into the list
  1199. +  **************************************************************************/
  1200. +static void add_server(struct server_record *s)
  1201.  {
  1202. -  int i;
  1203. -  time_t t = time(NULL);
  1204. +  struct server_record *s2;
  1205.  
  1206. -  for (i=0;i<num_names;i++)
  1207. -    if (names[i].valid && (groups || !ISGROUP(i)))
  1208. -      {
  1209. -    if ((names[i].ttl > 0) && (t > (names[i].start_time + names[i].ttl)))
  1210. -      names[i].valid = False;
  1211. -    else
  1212. -      {
  1213. -        if (name_equal(s,names[i].name,type,names[i].type)) {
  1214. -          return(i);
  1215. -        }
  1216. -      }
  1217. -      }
  1218. -  return -1;
  1219. +  if (!serverlist) {
  1220. +    serverlist = s;
  1221. +    s->prev = NULL;
  1222. +    s->next = NULL;
  1223. +    return;
  1224. +  }
  1225. +
  1226. +  for (s2 = serverlist; s2->next; s2 = s2->next) ;
  1227. +
  1228. +  s2->next = s;
  1229. +  s->next = NULL;
  1230. +  s->prev = s2;
  1231.  }
  1232.  
  1233. +/****************************************************************************
  1234. +  remove a name from the namelist. The pointer must be an element just 
  1235. +  retrieved
  1236. +  **************************************************************************/
  1237. +static void remove_name(struct name_record *n)
  1238. +{
  1239. +  struct name_record *nlist = namelist;
  1240. +  while (nlist && nlist != n) nlist = nlist->next;
  1241. +  if (nlist) {
  1242. +    if (nlist->next) nlist->next->prev = nlist->prev;
  1243. +    if (nlist->prev) nlist->prev->next = nlist->next;
  1244. +    free(nlist);
  1245. +  }
  1246. +}
  1247.  
  1248.  /****************************************************************************
  1249. -check names, and change any 0 IPs to myip
  1250. -****************************************************************************/
  1251. -static void check_names(void)
  1252. +  find a name in the namelist 
  1253. +  **************************************************************************/
  1254. +static struct name_record *find_name(struct nmb_name *n)
  1255.  {
  1256. -  int i;
  1257. -  int group_count=0;
  1258. +  struct name_record *ret;
  1259. +  for (ret = namelist; ret; ret = ret->next)
  1260. +    if (name_equal(&ret->name,n)) return(ret);
  1261.  
  1262. -  /* add the magic __SAMBA__ name */
  1263. -  add_host_name("__SAMBA__",0x20,&myip);
  1264. -  add_host_name("__SAMBA__",0x0,&myip);
  1265. +  return(NULL);
  1266. +}
  1267.  
  1268. -  for (i=0;i<num_names;i++)
  1269. -    if (names[i].valid) {
  1270. -      if (ISGROUP(i)) group_count++;
  1271. -    }
  1272. +/****************************************************************************
  1273. +  dump a copy of the name table
  1274. +  **************************************************************************/
  1275. +static void dump_names(void)
  1276. +{
  1277. +  time_t t = time(NULL);
  1278. +  struct name_record *n;
  1279. +  struct domain_record *d;
  1280.  
  1281. -  if (group_count == 0)
  1282. -    add_group_name(WORKGROUP);
  1283. +  DEBUG(3,("Dump of local name table:\n"));
  1284.  
  1285. +  for (n = namelist; n; n = n->next) {
  1286. +    DEBUG(3,("%s %s TTL=%d Unique=%s\n",
  1287. +         namestr(&n->name),
  1288. +         inet_ntoa(n->ip),
  1289. +         n->death_time?n->death_time-t:0,
  1290. +         BOOLSTR(n->unique)));
  1291. +    }
  1292.  
  1293. -  for (i=0;i<num_names;i++)
  1294. -    if (names[i].valid && strequal((char *)inet_ntoa(names[i].ip),"0.0.0.0"))
  1295. -      names[i].ip = (ISGROUP(i)?bcast_ip:myip);
  1296. +  DEBUG(3,("\nDump of domain list:\n"));
  1297. +  for (d = domainlist; d; d = d->next)
  1298. +    DEBUG(3,("%s %s\n",d->name,inet_ntoa(d->bcast_ip)));
  1299.  }
  1300.  
  1301.  
  1302.  /****************************************************************************
  1303. -dump a copy of the name table
  1304. -****************************************************************************/
  1305. -static void dump_names(void)
  1306. +  add a host entry to the name list
  1307. +  ****************************************************************************/
  1308. +static struct name_record *add_host_entry(char *name,int type,BOOL unique,int ttl,
  1309. +                      enum name_source source,
  1310. +                      struct in_addr ip)
  1311.  {
  1312. -  int i;
  1313. -  DEBUG(3,("Dump of local name table\n"));
  1314. -  for (i=0;i<num_names;i++)
  1315. -    if (names[i].valid) {
  1316. -      DEBUG(3,("%s %s %d %s",
  1317. -           names[i].name,inet_ntoa(names[i].ip),
  1318. -           names[i].ttl,BOOLSTR(names[i].isgroup)));
  1319. -      if (names[i].found_master) 
  1320. -    DEBUG(3,(" %s",inet_ntoa(names[i].master_ip)));
  1321. -      DEBUG(3,("\n"));
  1322. -    }
  1323. +  struct name_record *n;
  1324. +  struct name_record *n2=NULL;
  1325. +
  1326. +  n = (struct name_record *)malloc(sizeof(*n));
  1327. +  if (!n) return(NULL);
  1328. +
  1329. +  bzero((char *)n,sizeof(*n));
  1330. +
  1331. +  make_nmb_name(&n->name,name,type,scope);
  1332. +  if ((n2=find_name(&n->name))) {
  1333. +    free(n);
  1334. +    n = n2;
  1335. +  }
  1336. +
  1337. +  if (ttl) n->death_time = time(NULL)+ttl*3;
  1338. +  n->ip = ip;
  1339. +  n->unique = unique;
  1340. +  n->source = source;
  1341. +  
  1342. +  if (!n2) add_name(n);
  1343. +
  1344. +  DEBUG(3,("Added host entry %s at %s ttl=%d unique=%s\n",
  1345. +       namestr(&n->name),inet_ntoa(ip),ttl,BOOLSTR(unique)));
  1346. +
  1347. +  return(n);
  1348.  }
  1349.  
  1350.  
  1351.  /****************************************************************************
  1352. -load a netbios hosts file
  1353. -****************************************************************************/
  1354. -static void load_hosts_file(char *fname)
  1355. +  add a domain entry
  1356. +  ****************************************************************************/
  1357. +static struct domain_record *add_domain_entry(char *name,struct in_addr ip)
  1358.  {
  1359. -  int i;
  1360. -  FILE *f = fopen(fname,"r");
  1361. -  pstring line;
  1362. -  if (!f) 
  1363. -    {
  1364. -      DEBUG(2,("Not using non-existant lmhosts file %s\n",fname));
  1365. -      return;
  1366. -    }
  1367. +  struct domain_record *d;
  1368.  
  1369. -  while (!feof(f))
  1370. -    {
  1371. -      if (!fgets_slash(line,sizeof(pstring),f)) continue;
  1372. -      
  1373. -      if (*line == '#') continue;
  1374. +  d = (struct domain_record *)malloc(sizeof(*d));
  1375.  
  1376. -      {
  1377. -    string ip="",name="",flags="",extra="";
  1378. -    unsigned long a;
  1379. -    char *ptr;
  1380. -    int count = 0;
  1381. -    ptr = line;
  1382. -    if (next_token(&ptr,ip,NULL)) ++count;
  1383. -    if (next_token(&ptr,name,NULL)) ++count;
  1384. -    if (next_token(&ptr,flags,NULL)) ++count;
  1385. -    if (next_token(&ptr,extra,NULL)) ++count;
  1386. +  if (!d) return(NULL);
  1387.  
  1388. -    if (count <= 0) continue;
  1389. +  bzero((char *)d,sizeof(*d));
  1390.  
  1391. -    if (count > 0 && count < 2)
  1392. -      {
  1393. -        DEBUG(0,("Ill formed hosts line [%s]\n",line));        
  1394. -        continue;
  1395. -      }
  1396. +  StrnCpy(d->name,name,sizeof(d->name)-1);
  1397. +  d->bcast_ip = ip;
  1398.  
  1399. -    i = add_name();
  1400. -    if (i < 0) 
  1401. -      {
  1402. -        fclose(f);
  1403. -        return;
  1404. -      }
  1405. +  if (!*PrimaryGroup && ip_equal(bcast_ip,ip) && name[0] != '*') {
  1406. +    strcpy(PrimaryGroup,name);
  1407. +    strupper(PrimaryGroup);
  1408. +  }
  1409.  
  1410. -    a = interpret_addr(ip);
  1411. -    putip((char *)&names[i].ip,(char *)&a);
  1412. +  add_domain(d);
  1413.  
  1414. -    names[i].valid = True;
  1415. -    names[i].source = LMHOSTS;
  1416. +  ip = *interpret_addr2("255.255.255.255");
  1417. +  if (name[0] != '*') add_host_entry(name,0x1e,False,0,SELF,ip);      
  1418.  
  1419. -    StrnCpy(names[i].name,name,15);
  1420. -    if (strchr(flags,'G') || strchr(flags,'S'))
  1421. -      names[i].isgroup = True;
  1422. -    if (strchr(flags,'M') && !ISGROUP(i))
  1423. -      strcpy(myname,name);
  1424. -    if (strchr(flags,'U'))
  1425. -      names[i].unicast = True;
  1426. -    if (names[i].isgroup) 
  1427. -      names[i].type = 0xF0; /* hopefully invalid */
  1428. -    else
  1429. -      names[i].type = 0x20;
  1430. -      }      
  1431. -    }
  1432. +  DEBUG(3,("Added domain entry %s at %s\n",
  1433. +       name,inet_ntoa(ip)));
  1434.  
  1435. -  fclose(f);
  1436. +  return(d);
  1437.  }
  1438.  
  1439. -
  1440.  /****************************************************************************
  1441. -add a netbios group name
  1442. -****************************************************************************/
  1443. -static void add_group_name(char *name)
  1444. +  add a server entry
  1445. +  ****************************************************************************/
  1446. +static struct server_record *add_server_entry(char *name,int servertype,
  1447. +                          int ttl,char *comment)
  1448.  {
  1449. -  int i = add_name();
  1450. -  if (i < 0) 
  1451. -    return;
  1452. +  BOOL newentry=False;
  1453. +  struct server_record *s;
  1454. +
  1455. +  updatedlists=True;
  1456. +
  1457. +  for (s = serverlist; s; s = s->next)
  1458. +    if (strequal(name,s->name)) break;
  1459. +
  1460. +  if (!s) {
  1461. +    newentry = True;
  1462. +    s = (struct server_record *)malloc(sizeof(*s));
  1463. +
  1464. +    if (!s) return(NULL);
  1465. +
  1466. +    bzero((char *)s,sizeof(*s));
  1467. +  }
  1468. +
  1469. +  /* update the entry */
  1470. +  StrnCpy(s->name,name,sizeof(s->name)-1);
  1471. +  StrnCpy(s->comment,comment,sizeof(s->comment)-1);
  1472. +  s->servertype = servertype;
  1473. +  s->death_time = ttl?time(NULL)+ttl*3:0;
  1474. +  strupper(s->name);
  1475. +  if (s->servertype & SV_TYPE_DOMAIN_ENUM) strupper(s->comment);
  1476. +
  1477. +  if (!newentry) return(s);
  1478.  
  1479. -  bzero((char *)&names[i].ip,sizeof(names[i].ip));
  1480. +  add_server(s);
  1481.  
  1482. -  strcpy(names[i].name,name);
  1483. -  names[i].isgroup = True;
  1484. -  names[i].valid = True;
  1485. -  names[i].type = 0xF0;
  1486. -  names[i].source = SELF;
  1487. +  DEBUG(3,("Added server entry %s of type %x (%s)\n",
  1488. +       name,servertype,comment));
  1489. +
  1490. +  return(s);
  1491.  }
  1492.  
  1493. +
  1494.  /****************************************************************************
  1495. -add a host name
  1496. -****************************************************************************/
  1497. -static void add_host_name(char *name,int type,struct in_addr *ip)
  1498. +  add the magic samba names, useful for finding samba servers
  1499. +  **************************************************************************/
  1500. +static void add_my_names(void)
  1501.  {
  1502. -  int i;
  1503. +  struct in_addr ip = *interpret_addr2("0.0.0.0");
  1504.  
  1505. -  if (find_name(name,type,True) >= 0) return;
  1506. +  add_host_entry("__SAMBA__",0x20,True,0,SELF,ip);
  1507. +  add_host_entry("__SAMBA__",0x0,True,0,SELF,ip);
  1508. +  add_host_entry(myname,0x20,True,0,SELF,ip);
  1509. +  add_host_entry(myname,0x0,True,0,SELF,ip);
  1510. +  add_host_entry(myname,0x1f,True,0,SELF,ip); /* used for chat, I think */
  1511. +  if (!domainlist)
  1512. +    add_domain_entry(lp_workgroup(),bcast_ip);
  1513. +  add_server_entry(myname,
  1514. +           ServerType,
  1515. +           0,ServerComment);
  1516. +}
  1517.  
  1518. -  i = add_name();
  1519. -  if (i < 0) 
  1520. -    return;
  1521.  
  1522. -  names[i].ip = *ip;
  1523. -  strcpy(names[i].name,name);
  1524. -  names[i].valid = True;
  1525. -  names[i].start_time = time(NULL);
  1526. -  names[i].ttl = 0;
  1527. -  names[i].type = type;
  1528. -  names[i].source = SELF;
  1529. +/*******************************************************************
  1530. +  write out browse.dat
  1531. +  ******************************************************************/
  1532. +static void write_browse_list(void)
  1533. +{
  1534. +  struct server_record *s;
  1535. +  pstring fname,fnamenew;
  1536. +  FILE *f;
  1537. +  
  1538. +  updatecount++;
  1539. +
  1540. +  strcpy(fname,lp_lockdir());
  1541. +  trim_string(fname,NULL,"/");
  1542. +  strcat(fname,"/");
  1543. +  strcat(fname,SERVER_LIST);
  1544. +  strcpy(fnamenew,fname);
  1545. +  strcat(fnamenew,".");
  1546. +  
  1547. +  f = fopen(fnamenew,"w");
  1548. +  
  1549. +  if (!f) {
  1550. +    DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
  1551. +    return;
  1552. +  }
  1553. +  
  1554. +  for (s=serverlist; s ; s = s->next) {
  1555. +    /* don't list domains I don't have a master for */
  1556. +    if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
  1557. +    
  1558. +    fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
  1559. +  }
  1560. +  
  1561. +  
  1562. +  fclose(f);
  1563. +  unlink(fname);
  1564. +  rename(fnamenew,fname);   
  1565. +  DEBUG(3,("Wrote browse list %s\n",fname));
  1566.  }
  1567.  
  1568. -/****************************************************************************
  1569. -word out the length of a nmb message
  1570. -****************************************************************************/
  1571. -static int nmb_len(char *buf)
  1572. +/*******************************************************************
  1573. +  expire old names in the namelist and serverlist
  1574. +  ******************************************************************/
  1575. +static void expire_names(void)
  1576.  {
  1577. -int i;
  1578. -int ret = 12;
  1579. -char *p = buf;
  1580. -int qdcount = RSVAL(buf,4);
  1581. -int ancount = RSVAL(buf,6);
  1582. -int nscount = RSVAL(buf,8);
  1583. -int arcount = RSVAL(buf,10);
  1584. +  static time_t lastrun=0;
  1585. +  time_t t = time(NULL);
  1586. +  struct name_record *n;
  1587. +  struct name_record *next;
  1588. +  struct server_record *s;
  1589. +  struct server_record *nexts;
  1590. +
  1591. +  if (!lastrun) lastrun = t;
  1592. +  if (t < lastrun + 5) return;
  1593. +  lastrun = t;
  1594. +
  1595. +  /* expire old names */
  1596. +  for (n = namelist; n; n = next) {
  1597. +    if (n->death_time && n->death_time < t) {
  1598. +      DEBUG(3,("Removing dead name %s\n",
  1599. +           namestr(&n->name)));
  1600. +      next = n->next;
  1601. +      if (n->prev) n->prev->next = n->next;
  1602. +      if (n->next) n->next->prev = n->prev;
  1603. +      if (namelist == n) namelist = n->next; 
  1604. +      free(n);
  1605. +    } else {
  1606. +      next = n->next;
  1607. +    }
  1608. +  }
  1609.  
  1610. -/* check for insane qdcount values? */
  1611. -if (qdcount > 100 || qdcount < 0)
  1612. -  {
  1613. -    DEBUG(6,("Invalid qdcount? qdcount=%d\n",qdcount));
  1614. -    return(0);
  1615. +  /* expire old entries in the serverlist */
  1616. +  for (s = serverlist; s; s = nexts) {
  1617. +    if (s->death_time && s->death_time < t) {
  1618. +      DEBUG(3,("Removing dead server %s\n",s->name));
  1619. +      updatedlists = True;
  1620. +      nexts = s->next;
  1621. +      if (s->prev) s->prev->next = s->next;
  1622. +      if (s->next) s->next->prev = s->prev;
  1623. +      if (serverlist == s) serverlist = s->next; 
  1624. +      free(s);
  1625. +    } else {
  1626. +      nexts = s->next;
  1627. +    }
  1628.    }
  1629. +}
  1630.  
  1631. -for (i=0;i<qdcount;i++)
  1632. -  {
  1633. -    p = buf + ret;
  1634. -    ret += name_len(p) + 4;
  1635. +
  1636. +/*******************************************************************
  1637. +  delete old names from the namelist
  1638. +  ******************************************************************/
  1639. +static void housekeeping(void)
  1640. +{
  1641. +  time_t t = time(NULL);
  1642. +
  1643. +  expire_names();
  1644. +
  1645. +  /* write out the browse.dat database for smbd to get */
  1646. +  if (updatedlists) {
  1647. +    write_browse_list();
  1648. +    updatedlists = False;
  1649.    }
  1650.  
  1651. -for (i=0;i<(ancount + nscount + arcount);i++)
  1652.    {
  1653. -    int rdlength;
  1654. -    p = buf + ret;
  1655. -    ret += name_len(p) + 8;
  1656. -    p = buf + ret;
  1657. -    rdlength = RSVAL(p,0);
  1658. -    ret += rdlength + 2;
  1659. +    /* occasionally check to see if the master browser is around */
  1660. +    static time_t lastrun=0;
  1661. +    if (!lastrun) lastrun = t;
  1662. +    if (t < lastrun + 5*60) return;
  1663. +    lastrun = t;
  1664. +
  1665. +    if (!AM_MASTER && *PrimaryGroup &&
  1666. +    !name_query(ClientNMB,PrimaryGroup,0x1d,True,False,
  1667. +            bcast_ip,NULL,queue_packet)) {
  1668. +      DEBUG(2,("Forcing election on %s\n",PrimaryGroup));
  1669. +      needelection = True;
  1670. +    }
  1671.    }
  1672. -
  1673. -return(ret);
  1674.  }
  1675.  
  1676. +
  1677.  /****************************************************************************
  1678. -receive a name message. timeout is in milliseconds
  1679. -****************************************************************************/
  1680. -static int receive_nmb(char *buffer,int timeout)
  1681. +  reload the services file
  1682. +  **************************************************************************/
  1683. +BOOL reload_services(BOOL test)
  1684.  {
  1685. -  int ret = read_max_udp(Client,buffer,sizeof(pstring),timeout);
  1686. +  BOOL ret;
  1687. +  extern fstring remote_machine;
  1688. +
  1689. +  strcpy(remote_machine,"nmbd");
  1690.  
  1691. -  if (ret < 0)
  1692. +  if (lp_loaded())
  1693.      {
  1694. -      DEBUG(0,("No bytes from client\n"));
  1695. -      if (!is_daemon)
  1696. +      pstring fname;
  1697. +      strcpy(fname,lp_configfile());
  1698. +      if (file_exist(fname,NULL) && !strcsequal(fname,servicesf))
  1699.      {
  1700. -      close_sockets();
  1701. -      exit(0);
  1702. +      strcpy(servicesf,fname);
  1703. +      test = False;
  1704.      }
  1705.      }
  1706. -  
  1707. -  if (ret <= 1)
  1708. -    return 0;
  1709.  
  1710. -  log_in(buffer,ret);
  1711. +  if (test && !lp_file_list_changed())
  1712. +    return(True);
  1713.  
  1714. -  DEBUG(3,("received packet from (%s) nmb_len=%d len=%d\n",
  1715. -    inet_ntoa(lastip),nmb_len(buffer),ret));
  1716. +  ret = lp_load(servicesf,True);
  1717.  
  1718. -  num_good_receives++;
  1719. +  /* perhaps the config filename is now set */
  1720. +  if (!test)
  1721. +    reload_services(True);
  1722.  
  1723.    return(ret);
  1724.  }
  1725.  
  1726. +
  1727. +
  1728.  /****************************************************************************
  1729. -send a name message
  1730. +load a netbios hosts file
  1731.  ****************************************************************************/
  1732. -static BOOL send_nmb(char *buf, int len, struct in_addr *ip,int port)
  1733. +static void load_hosts_file(char *fname)
  1734.  {
  1735. -  BOOL ret;
  1736. -  struct sockaddr_in sock_out;
  1737. +  FILE *f = fopen(fname,"r");
  1738. +  pstring line;
  1739. +  if (!f) {
  1740. +    DEBUG(2,("Can't open lmhosts file %s\n",fname));
  1741. +    return;
  1742. +  }
  1743.  
  1744. -  /* set the address and port */
  1745. -  bzero((char *)&sock_out,sizeof(sock_out));
  1746. -  putip((char *)&sock_out.sin_addr,(char *)ip);
  1747. -  sock_out.sin_port = htons( port );
  1748. -  sock_out.sin_family = AF_INET;
  1749. -  
  1750. -  /* log the packet */
  1751. -  log_out(buf,len);
  1752. -
  1753. -  if (DEBUGLEVEL > 0)
  1754. -    DEBUG(3,("sending a packet of len %d to (%s) on port 137 of type DGRAM\n",
  1755. -      len,inet_ntoa(*ip)));
  1756. -    
  1757. -  /* send it */
  1758. -  ret = (sendto(Client,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
  1759. +  while (!feof(f))
  1760. +    {
  1761. +      if (!fgets_slash(line,sizeof(pstring),f)) continue;
  1762. +      
  1763. +      if (*line == '#') continue;
  1764.  
  1765. -  if (!ret)
  1766. -    DEBUG(0,("Send packet failed. ERRNO=%d\n",errno));
  1767. +      {
  1768. +    BOOL group=False;
  1769. +    string ip="",name="",flags="",extra="";
  1770. +    char *ptr;
  1771. +    int count = 0;
  1772. +    struct in_addr ipaddr;
  1773. +    enum name_source source = LMHOSTS;
  1774.  
  1775. -  if (ret)
  1776. -    num_good_sends++;
  1777. +    ptr = line;
  1778.  
  1779. -  return(ret);
  1780. -}
  1781. +    if (next_token(&ptr,ip,NULL)) ++count;
  1782. +    if (next_token(&ptr,name,NULL)) ++count;
  1783. +    if (next_token(&ptr,flags,NULL)) ++count;
  1784. +    if (next_token(&ptr,extra,NULL)) ++count;
  1785.  
  1786. -/*******************************************************************
  1787. -check if an IP is on my net
  1788. -********************************************************************/
  1789. -static BOOL is_mynet(struct in_addr ip)
  1790. -{
  1791. -  unsigned int net1,net2,nmask,subnet1,subnet2;
  1792. +    if (count <= 0) continue;
  1793.  
  1794. -  nmask   = *(unsigned int *)&Netmask;
  1795. -  net1    = (*(unsigned int *)&myip);
  1796. -  subnet1 = net1 & nmask;
  1797. -  net2    = (*(unsigned int *)&ip);
  1798. -  subnet2 = net2 & nmask;
  1799. -        
  1800. -  return((net1 != net2) && (subnet1 == subnet2));
  1801. -}
  1802. +    if (count > 0 && count < 2)
  1803. +      {
  1804. +        DEBUG(0,("Ill formed hosts line [%s]\n",line));        
  1805. +        continue;
  1806. +      }
  1807.  
  1808. -/****************************************************************************
  1809. -interpret a node status response
  1810. -****************************************************************************/
  1811. -static void interpret_node_status(char *inbuf, char *master)
  1812. -{
  1813. -  int level = master?3:0;
  1814. -  char *p = inbuf + 12 + name_len(inbuf+12) + 10;
  1815. -  int numnames = CVAL(p,0);
  1816. -  DEBUG(level,("received %d names\n",numnames));
  1817. +    if (strchr(flags,'G') || strchr(flags,'S'))
  1818. +      group = True;
  1819.  
  1820. -  p += 1;
  1821. -  while (numnames--)
  1822. -    {
  1823. -      char qname[17];
  1824. -      int type;
  1825. -      fstring flags="";
  1826. -      StrnCpy(qname,p,15);
  1827. -      type = CVAL(p,15);
  1828. -      p += 16;
  1829. -
  1830. -      if (p[0] & 0x80) strcat(flags,"<GROUP> ");
  1831. -      if (p[0] & 0x60 == 0) strcat(flags,"B ");
  1832. -      if (p[0] & 0x60 == 1) strcat(flags,"P ");
  1833. -      if (p[0] & 0x60 == 2) strcat(flags,"M ");
  1834. -      if (p[0] & 0x60 == 3) strcat(flags,"_ ");
  1835. -      if (p[0] & 0x10) strcat(flags,"<DEREGISTERING> ");
  1836. -      if (p[0] & 0x08) strcat(flags,"<CONFLICT> ");
  1837. -      if (p[0] & 0x04) strcat(flags,"<ACTIVE> ");
  1838. -      if (p[0] & 0x02) strcat(flags,"<PERMANENT> ");
  1839. +    if (strchr(flags,'M') && !group) {
  1840. +      source = SELF;
  1841. +      strcpy(myname,name);
  1842. +    }
  1843. +
  1844. +    ipaddr = *interpret_addr2(ip);
  1845.  
  1846. -      if (master && type == 0x1d) {
  1847. -    StrnCpy(master,qname,15);
  1848. +    if (group) {
  1849. +      add_domain_entry(name,ipaddr);
  1850. +    } else {
  1851. +      add_host_entry(name,0x20,True,0,source,ipaddr);
  1852. +    }
  1853.        }
  1854. -      
  1855. -      DEBUG(level,("\t%s (type=0x%x)\t%s\n",qname,type,flags));
  1856. -      p+=2;
  1857.      }
  1858. -  DEBUG(level,("num_good_sends=%d num_good_receives=%d\n",
  1859. -           IVAL(p,20),IVAL(p,24)));
  1860. +
  1861. +  fclose(f);
  1862.  }
  1863.  
  1864. +/*******************************************************************
  1865. +  check if 2 IPs are on the same net
  1866. +  we will assume the local netmask, although this could be wrong XXXX
  1867. +  ******************************************************************/
  1868. +static BOOL same_net(struct in_addr ip1,struct in_addr ip2)
  1869. +{
  1870. +  unsigned long net1,net2,nmask;
  1871. +
  1872. +  nmask = ntohl(Netmask.s_addr);
  1873. +  net1 = ntohl(ip1.s_addr);
  1874. +  net2 = ntohl(ip2.s_addr);
  1875. +        
  1876. +  return((net1 & nmask) == (net2 & nmask));
  1877. +}
  1878.  
  1879.  /****************************************************************************
  1880. -show a nmb message
  1881. -****************************************************************************/
  1882. -static void show_nmb(char *inbuf)
  1883. +  send an election packet
  1884. +  **************************************************************************/
  1885. +static void send_election(char *group,uint32 criterion,int timeup,char *name)
  1886.  {
  1887. -  int i,l;
  1888. -  int name_trn_id = RSVAL(inbuf,0);
  1889. -  int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
  1890. -  int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  1891. -  int rcode = CVAL(inbuf,3) & 0xF;
  1892. -  int qdcount = RSVAL(inbuf,4);
  1893. -  int ancount = RSVAL(inbuf,6);
  1894. -  int nscount = RSVAL(inbuf,8);
  1895. -  int arcount = RSVAL(inbuf,10);
  1896. -  char name[100];
  1897. +  pstring outbuf;
  1898. +  char *p;
  1899.  
  1900. -  if (DEBUGLEVEL < 3) return;
  1901. +  DEBUG(2,("Sending election to %s for workgroup %s\n",
  1902. +       inet_ntoa(bcast_ip),group));       
  1903.  
  1904. -  DEBUG(3,("\nPACKET INTERPRETATION\n"));
  1905. +  bzero(outbuf,sizeof(outbuf));
  1906. +  p = outbuf;
  1907. +  CVAL(p,0) = 8; /* election */
  1908. +  p++;
  1909.  
  1910. -  if (opcode == 5 && ((nm_flags & ~1) == 0x10) && rcode == 0)
  1911. -    DEBUG(3,("NAME REGISTRATION REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1912. +  CVAL(p,0) = ELECTION_VERSION;
  1913. +  SIVAL(p,1,criterion);
  1914. +  SIVAL(p,5,timeup*1000); /* ms - despite the spec */
  1915. +  p += 13;
  1916. +  strcpy(p,name);
  1917. +  strupper(p);
  1918. +  p = skip_string(p,1);
  1919.  
  1920. -  if (opcode == 5 && ((nm_flags & ~1) == 0x00) && rcode == 0)
  1921. -    DEBUG(3,("NAME OVERWRITE REQUEST AND DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1922. -  
  1923. -  if (opcode == 9 && ((nm_flags & ~1) == 0x00) && rcode == 0)
  1924. -    DEBUG(3,("NAME REFRESH REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1925. +  send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  1926. +         name,group,0,0x1e,bcast_ip,myip);
  1927. +}
  1928.  
  1929. -  if (opcode == 8)
  1930. -    DEBUG(3,("NAME REFRESH (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1931. -  
  1932. -  if (opcode == 5 && nm_flags == 0x58 && rcode == 0)
  1933. -    DEBUG(3,("POSITIVE NAME REGISTRATION RESPONSE\n"));
  1934. -  
  1935. -  if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode != 7)
  1936. -    DEBUG(3,("NEGATIVE NAME REGISTRATION RESPONSE\n"));
  1937. -  
  1938. -  if (opcode == 5 && nm_flags == 0x50 && rcode == 0)
  1939. -    DEBUG(3,("END-NODE CHALLENGE REGISTRATION RESPONSE\n"));
  1940. -  
  1941. -  if (opcode == 5 && nm_flags == 0x58 && rcode != 0 && rcode == 7)
  1942. -    DEBUG(3,("NAME CONFLICT DEMAND\n"));
  1943. -  
  1944. -  if (opcode == 6 && (nm_flags&~1) == 0x00 && rcode == 0)
  1945. -    DEBUG(3,("NAME RELEASE REQUEST & DEMAND (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1946. -  
  1947. -  if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode == 0)
  1948. -    DEBUG(3,("POSITIVE NAME RELEASE RESPONSE\n"));
  1949. -  
  1950. -  if (opcode == 6 && (nm_flags&~1) == 0x40 && rcode != 0)
  1951. -    DEBUG(3,("NEGATIVE NAME RELEASE RESPONSE\n"));
  1952. -  
  1953. -  if (opcode == 0 && (nm_flags&~1) == 0x10 && rcode == 0)
  1954. -    DEBUG(3,("NAME QUERY REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1955. -  
  1956. -  if (opcode == 0 && (nm_flags&~0x28) == 0x50 && rcode == 0)
  1957. -    DEBUG(3,("POSITIVE NAME QUERY RESPONSE\n"));
  1958. -  
  1959. -  if (opcode == 0 && (nm_flags&~0x08) == 0x50 && rcode != 0)
  1960. -    DEBUG(3,("NEGATIVE NAME QUERY RESPONSE\n"));
  1961. -  
  1962. -  if (opcode == 0 && nm_flags == 0x10 && rcode == 0)
  1963. -    DEBUG(3,("REDIRECT NAME QUERY RESPONSE\n"));
  1964.  
  1965. -  if (opcode == 7 && nm_flags == 0x80 && rcode == 0)
  1966. -    DEBUG(3,("WAIT FOR ACKNOWLEDGEMENT RESPONSE\n"));
  1967. -  
  1968. -  if (opcode == 0 && (nm_flags&~1) == 0x00 && rcode == 0)
  1969. -    DEBUG(3,("NODE STATUS REQUEST (%s)\n",nm_flags&1?"Broadcast":"Unicast"));
  1970. +/****************************************************************************
  1971. +  send a backup list response
  1972. +  **************************************************************************/
  1973. +static void send_backup_list(char *name,int token,struct nmb_name *to,
  1974. +                 struct in_addr ip)
  1975. +{
  1976. +  pstring outbuf;
  1977. +  char *p;
  1978.  
  1979. -  if (opcode == 0 && nm_flags == 0x40 && rcode == 0)
  1980. -    {
  1981. -      DEBUG(3,("NODE STATUS RESPONSE\n"));
  1982. -      interpret_node_status(inbuf,NULL);
  1983. -    }
  1984. -  
  1985. -  
  1986. -  DEBUG(3,("name_trn_id=0x%x\nopcode=0x%x\nnm_flags=0x%x\nrcode=0x%x\n",
  1987. -    name_trn_id,opcode,nm_flags,rcode));
  1988. -  DEBUG(3,("qdcount=%d\nancount=%d\nnscount=%d\narcount=%d\n",
  1989. -    qdcount,ancount,nscount,arcount));
  1990. +  DEBUG(2,("Sending backup list to %s for workgroup %s\n",
  1991. +       inet_ntoa(ip),PrimaryGroup));       
  1992.  
  1993. -  l = 12;
  1994. -  for (i=0;i<qdcount;i++)
  1995. -    {
  1996. -      int type,class;
  1997. -      DEBUG(3,("QUESTION %d\n",i));
  1998. -      name_extract(inbuf,l,name);
  1999. -      l += name_len(inbuf+l);
  2000. -      type = RSVAL(inbuf+l,0);
  2001. -      class = RSVAL(inbuf+l,2);
  2002. -      l += 4;
  2003. -      DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
  2004. -    }
  2005. +  bzero(outbuf,sizeof(outbuf));
  2006. +  p = outbuf;
  2007. +  CVAL(p,0) = 10; /* backup list response */
  2008. +  p++;
  2009.  
  2010. -  for (i=0;i<(ancount + nscount + arcount);i++)
  2011. -    {
  2012. -      int type,class,ttl,rdlength;
  2013. -      DEBUG(3,("RESOURCE %d\n",i));
  2014. -      name_extract(inbuf,l,name);
  2015. -      l += name_len(inbuf + l);
  2016. -      type = RSVAL(inbuf+l,0);
  2017. -      class = RSVAL(inbuf+l,2);
  2018. -      ttl = RIVAL(inbuf+l,4);
  2019. -      rdlength = RSVAL(inbuf+l,8);
  2020. -      l += 10 + rdlength;
  2021. -      DEBUG(3,("\t%s\n\ttype=0x%x\n\tclass=0x%x\n",name,type,class));
  2022. -      DEBUG(3,("\tttl=%d\n\trdlength=%d\n",ttl,rdlength));
  2023. -    }
  2024. +  CVAL(p,0) = 1; /* count */
  2025. +  SIVAL(p,1,token);
  2026. +  p += 5; 
  2027. +  strcpy(p,name);
  2028. +  strupper(p);
  2029. +  p = skip_string(p,1) + 1;
  2030.  
  2031. -  DEBUG(3,("\n"));
  2032. -  
  2033. +  send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  2034. +         myname,to->name,0,to->name_type,ip,myip);
  2035.  }
  2036.  
  2037.  
  2038. -/****************************************************************************
  2039. -do a netbios name query to find someones IP
  2040. -****************************************************************************/
  2041. -static BOOL name_query(char *name, char name_type, BOOL bcast,
  2042. -               struct in_addr to_ip, struct in_addr *ip, void (*fn)())
  2043. +/*******************************************************************
  2044. +  become the master browser
  2045. +  ******************************************************************/
  2046. +static void become_master(void)
  2047.  {
  2048. -  BOOL found=False;
  2049. -  pstring inbuf,outbuf;
  2050. -  static uint16 name_trn_id = 0x6242;
  2051. -  char *p;
  2052. -  int retries = 3;
  2053. -  int retry_time = bcast?250:5000;
  2054. -  struct timeval tval;
  2055. -
  2056. -  bzero(inbuf,sizeof(inbuf));
  2057. -  bzero(outbuf,sizeof(outbuf));
  2058. -
  2059. -  name_trn_id += getpid() % 100;
  2060. -  name_trn_id = (name_trn_id % 0x7FFF);
  2061. +  DEBUG(2,("Becoming master for %s\n",PrimaryGroup));
  2062.  
  2063. -  RSSVAL(outbuf,0,name_trn_id);
  2064. -  CVAL(outbuf,2) = 0x1;
  2065. -  CVAL(outbuf,3) = bcast?(1<<4):0;
  2066. -  RSSVAL(outbuf,4,1);
  2067. -  RSSVAL(outbuf,6,0);
  2068. -  RSSVAL(outbuf,8,0);
  2069. -  RSSVAL(outbuf,10,0);  
  2070. -  p = outbuf+12;
  2071. -  name_mangle(name,p,name_type);
  2072. -  p += name_len(p);
  2073. -  RSSVAL(p,0,0x20);
  2074. -  RSSVAL(p,2,0x1);
  2075. -  p += 4;
  2076. -
  2077. -  DEBUG(2,("Sending name query for %s\n",name));
  2078. -
  2079. -  show_nmb(outbuf);
  2080. -
  2081. -  GetTimeOfDay(&tval);
  2082. -
  2083. -  if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
  2084. -    return False;
  2085. -  retries--;
  2086. +  ServerType |= SV_TYPE_MASTER_BROWSER;
  2087. +  ServerType |= SV_TYPE_BACKUP_BROWSER;
  2088. +  ElectionCriterion |= 0x5;
  2089.  
  2090. -  while (1)
  2091. -    {
  2092. -      struct timeval tval2;
  2093. -      GetTimeOfDay(&tval2);
  2094. -      if (TvalDiff(&tval,&tval2) > retry_time) {
  2095. -    if (!retries) break;
  2096. -    if (!found && !send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
  2097. -      return False;
  2098. -    GetTimeOfDay(&tval);
  2099. -    retries--;
  2100. -      }
  2101. +  add_host_entry(PrimaryGroup,0x1d,True,0,SELF,myip);
  2102. +  add_host_entry(PrimaryGroup,0x0,False,0,SELF,myip);
  2103. +  add_host_entry(MSBROWSE,1,False,0,SELF,myip);
  2104. +  add_server_entry(PrimaryGroup,SV_TYPE_DOMAIN_ENUM,0,myname);
  2105. +  add_server_entry(myname,ServerType,0,ServerComment);    
  2106.  
  2107. -      if (receive_nmb(inbuf,90))
  2108. -    {     
  2109. -      int rec_name_trn_id = RSVAL(inbuf,0);
  2110. -      int opcode = (CVAL(inbuf,2) >> 3) & 0xF;
  2111. -      int rcode = CVAL(inbuf,3) & 0xF;
  2112. -      int response = (CVAL(inbuf,2)>>7);
  2113. -      int qdcount = RSVAL(inbuf,4);
  2114. -      int ancount = RSVAL(inbuf,6);
  2115. -      show_nmb(inbuf);
  2116. -
  2117. -      /* is it a positive response to our request? */
  2118. -      if ((rec_name_trn_id == name_trn_id) && response) {
  2119. -        if (opcode == 0 && qdcount==0 && ancount==1 && rcode == 0) {
  2120. -          putip((char *)ip,inbuf + 12 + name_len(inbuf+12) + 12);
  2121. -          DEBUG(2,("Got a positive name query response from %s",
  2122. -               inet_ntoa(lastip)));
  2123. -          DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
  2124. -          found=True; retries=0;
  2125. -          continue;
  2126. -        } else {
  2127. -          /* some other sort of response, yuck */
  2128. -          DEBUG(2,("Unknown response\n"));
  2129. -          continue;
  2130. -        }
  2131. -      } else {
  2132. -        if (fn) fn(inbuf);
  2133. -      }
  2134. -    }
  2135. -    }
  2136. +  announce_request(PrimaryGroup);
  2137.  
  2138. -  return(found);
  2139. +  needannounce = True;
  2140.  }
  2141.  
  2142. -/****************************************************************************
  2143. -do a netbios name status to a host
  2144. -****************************************************************************/
  2145. -static BOOL name_status(char *name,int type,struct in_addr to_ip,void (*fn)(),
  2146. -                        char *master)
  2147. +
  2148. +/*******************************************************************
  2149. +  unbecome the master browser
  2150. +  ******************************************************************/
  2151. +static void become_nonmaster(void)
  2152.  {
  2153. -  pstring inbuf,outbuf;
  2154. -  static uint16 name_trn_id = 0x4262;
  2155. -  char *p;
  2156. -  int retries = 3;
  2157. -  int retry_time = 5000;
  2158. -  struct timeval tval;
  2159. +  struct name_record *n;
  2160. +  struct nmb_name nn;
  2161.  
  2162. -  bzero(inbuf,sizeof(inbuf));
  2163. -  bzero(outbuf,sizeof(outbuf));
  2164. +  DEBUG(2,("Becoming non-master for %s\n",PrimaryGroup));
  2165. +
  2166. +  ServerType &= ~SV_TYPE_MASTER_BROWSER;
  2167. +  ElectionCriterion &= ~0x4;
  2168.  
  2169. -  if (!fn)
  2170. -    DEBUG(1,("Querying status of name %s\n",name));
  2171. +  make_nmb_name(&nn,PrimaryGroup,0x1d,scope);
  2172. +  n = find_name(&nn);
  2173. +  if (n && n->source == SELF) remove_name(n);
  2174.  
  2175. -  name_trn_id += getpid() % 100;
  2176. -  name_trn_id = (name_trn_id % 10000);
  2177. +  make_nmb_name(&nn,MSBROWSE,1,scope);
  2178. +  n = find_name(&nn);
  2179. +  if (n && n->source == SELF) remove_name(n);
  2180. +}
  2181.  
  2182. -  RSSVAL(outbuf,0,name_trn_id);
  2183. -  CVAL(outbuf,2) = 0;
  2184. -  CVAL(outbuf,3) = 0x0;
  2185. -  RSSVAL(outbuf,4,1);
  2186. -  RSSVAL(outbuf,6,0);
  2187. -  RSSVAL(outbuf,8,0);
  2188. -  RSSVAL(outbuf,10,0);  
  2189. -  p = outbuf+12;
  2190. -  name_mangle(name,p,type);
  2191. -  p += name_len(p);
  2192. -  RSSVAL(p,0,0x21);
  2193. -  RSSVAL(p,2,0x1);
  2194. -  p += 4;
  2195. -
  2196. -  DEBUG(fn?3:2,("Sending name status query for %s\n",name));
  2197.  
  2198. -  show_nmb(outbuf);
  2199. +/*******************************************************************
  2200. +  run the election
  2201. +  ******************************************************************/
  2202. +static void run_election(void)
  2203. +{
  2204. +  time_t t = time(NULL);
  2205. +  static time_t lastime = 0;
  2206.  
  2207. -  GetTimeOfDay(&tval);
  2208. +  if (!*PrimaryGroup || !RunningElection) return;
  2209.  
  2210. -  if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
  2211. -    return False;
  2212. -  
  2213. -  while (1)
  2214. -    {
  2215. -      struct timeval tval2;
  2216. -      GetTimeOfDay(&tval2);
  2217. -      if (TvalDiff(&tval,&tval2) > retry_time) {
  2218. -    if (!retries) break;
  2219. -    if (!send_nmb(outbuf,nmb_len(outbuf), &to_ip, 137))
  2220. -      return False;
  2221. -    GetTimeOfDay(&tval);
  2222. -    retries--;    
  2223. -      }
  2224. -      
  2225. -      if (receive_nmb(inbuf,90))
  2226. -    {
  2227. -      int rec_name_trn_id = RSVAL(inbuf,0);
  2228. -      int rcode = CVAL(inbuf,3) & 0xF;
  2229. -      int response = (CVAL(inbuf,2)>>7);
  2230. -      int qdcount = RSVAL(inbuf,4);
  2231. -      int ancount = RSVAL(inbuf,6);
  2232. -
  2233. -      show_nmb(inbuf);
  2234. -      
  2235. -      /* is it a positive response to our request? */
  2236. -      if (response && (rec_name_trn_id == name_trn_id)) {
  2237. -        if (rcode==0 && ancount==1 && qdcount==0) {
  2238. -          DEBUG(fn?3:0,("Got a positive node status response from %s\n",
  2239. -                inet_ntoa(lastip)));
  2240. -          interpret_node_status(inbuf, master);
  2241. -          return(True);
  2242. -        }
  2243. -        return(False);
  2244. -      }
  2245. -      if (fn) fn(inbuf);
  2246. -    }
  2247. -    }
  2248. +  /* send election packets once a second */
  2249. +  if (lastime &&
  2250. +      t-lastime <= 0) return;
  2251.  
  2252. -  DEBUG(0,("No response (this is not unusual)\n"));
  2253. +  lastime = t;
  2254.  
  2255. -  return(False);
  2256. +  send_election(PrimaryGroup,ElectionCriterion,t-StartupTime,myname);
  2257. +
  2258. +  if (ElectionCount++ < 4) return;
  2259. +   
  2260. +  /* I won! now what :-) */
  2261. +  RunningElection = False;
  2262. +  DEBUG(2,(">>> Won election on %s <<<\n",PrimaryGroup));
  2263. +  become_master();
  2264.  }
  2265.  
  2266.  
  2267.  /****************************************************************************
  2268. -reply to a reg request
  2269. -****************************************************************************/
  2270. -static void reply_name_reg(char *inbuf)
  2271. +  construct a host announcement unicast
  2272. +  **************************************************************************/
  2273. +static void announce_host(struct domain_record *d,char *my_name,char *comment)
  2274.  {
  2275. +  time_t t = time(NULL);
  2276.    pstring outbuf;
  2277. -  int rec_name_trn_id = RSVAL(inbuf,0);
  2278. -  char qname[100]="";
  2279. -  int ttl;
  2280. -  char *p = inbuf;
  2281. -  struct in_addr ip;
  2282. -  int n=0;
  2283. -  int name_type;
  2284. -  unsigned char nb_flags;
  2285. -  int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  2286. -  int bcast = (nm_flags&1);
  2287. -  struct in_addr tmpip;
  2288. -  
  2289. -  bzero(outbuf,sizeof(outbuf));
  2290. +  char *p;
  2291. +  char *namep;
  2292. +  char *stypep;
  2293. +  char *commentp;
  2294. +
  2295. +  if (needannounce) {
  2296. +    /* drop back to a max 3 minute announce - this is to prevent a
  2297. +       single lost packet from stuffing things up for too long */
  2298. +    d->announce_interval = MIN(d->announce_interval,3*60);
  2299. +    d->lastannounce_time = t - (d->announce_interval+1);
  2300. +  }
  2301.  
  2302. -  name_type = name_extract(inbuf,12,qname);
  2303. +  /* announce every minute at first then progress to every 12 mins */
  2304. +  if (d->lastannounce_time && 
  2305. +      (t - d->lastannounce_time) < d->announce_interval)
  2306. +    return;
  2307.  
  2308. -  p += 12;
  2309. -  p += name_len(p);
  2310. -  p += 4;
  2311. -  p += name_len(p);
  2312. -  p += 4;
  2313. -  ttl = RIVAL(p,0);
  2314. -  nb_flags = CVAL(p,6);
  2315. -  p += 8;
  2316. -  putip((char *)&ip,p);
  2317. -
  2318. -  DEBUG(2,("Name registration request for %s (%s) nb_flags=0x%x ntype=%d\n",
  2319. -    qname,inet_ntoa(ip),nb_flags,name_type));
  2320. -
  2321. -  if ((nb_flags&0x80) == 0 && (name_type != 0x1d)) {
  2322. -    if (ttl==0) ttl = NMBD_MAX_TTL;
  2323. -    ttl = MIN(ttl,NMBD_MAX_TTL);
  2324. +  if (d->announce_interval < 12*60) d->announce_interval += 60;
  2325. +  d->lastannounce_time = t;
  2326.  
  2327. -    n = find_name(qname,name_type,True);
  2328. +  DEBUG(2,("Sending announcement to %s for workgroup %s type=%d\n",
  2329. +       inet_ntoa(d->bcast_ip),d->name));       
  2330.  
  2331. -    if (n>=0 && names[n].source != REGISTER && names[n].source != DNS)
  2332. -      return;
  2333. +  if (!*comment) comment = "NoComment";
  2334. +  if (!*my_name) my_name = "NoName";
  2335.  
  2336. -    if (n<0)
  2337. -      n = add_name();
  2338. -    if (n<0) return;
  2339. -
  2340. -    bzero(&names[n],sizeof(names[n]));
  2341. -
  2342. -    StrnCpy(names[n].name,qname,15);
  2343. -    names[n].type = name_type;
  2344. -    names[n].unicast = !dns_serve || is_mynet(ip);
  2345. -    names[n].ip = ip;
  2346. -    names[n].valid = True;
  2347. -    names[n].ttl = ttl;
  2348. -    names[n].source = REGISTER;
  2349. -    names[n].start_time = time(NULL);
  2350. -    DEBUG(2,("Added %s with ttl %d as (%s) (uni=%s)\n",
  2351. -         qname,names[n].ttl,inet_ntoa(ip),BOOLSTR(names[n].unicast)));
  2352. -  }
  2353. +  if (strlen(comment) > 43) comment[43] = 0;  
  2354.  
  2355. -  if (bcast) return;
  2356. +  bzero(outbuf,sizeof(outbuf));
  2357. +  CVAL(outbuf,0) = 1; /* host announce */
  2358. +  p = outbuf+1;
  2359.  
  2360. -  /* Send a POSITIVE NAME REGISTRATION RESPONSE */
  2361. -  RSSVAL(outbuf,0,rec_name_trn_id);
  2362. -  CVAL(outbuf,2) = (1<<7) | (5<<3) | 5;
  2363. -  CVAL(outbuf,3) = (1<<7);
  2364. -  RSSVAL(outbuf,4,0);
  2365. -  RSSVAL(outbuf,6,1);
  2366. -  RSSVAL(outbuf,8,0);
  2367. -  RSSVAL(outbuf,10,0);  
  2368. -  p = outbuf+12;
  2369. -  strcpy(p,inbuf+12);
  2370. -  p += name_len(p);
  2371. -  RSSVAL(p,0,0x20);
  2372. -  RSSVAL(p,2,0x1);
  2373. -  /* we want them to refresh in case we die */
  2374. -  if (!ttl) ttl = 15*60;
  2375. -  ttl = MIN(ttl,15*60);
  2376. -  RSIVAL(p,4,ttl);
  2377. -
  2378. -  RSSVAL(p,8,6);
  2379. -  RSSVAL(p,10,nb_flags);  
  2380. -  p += 12;
  2381. -  putip(p,&ip);  
  2382. -  p += 4;
  2383. -
  2384. -  DEBUG(2,("Sending a positive registration response\n"));
  2385. -  if (DEBUGLEVEL > 2)
  2386. -    show_nmb(outbuf);
  2387. -
  2388. -  tmpip = lastip;
  2389. -  num_good_sends++;
  2390. -  send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
  2391. +  CVAL(p,0) = updatecount;
  2392. +  SIVAL(p,1,d->announce_interval*1000); /* ms - despite the spec */
  2393. +  namep = p+5;
  2394. +  StrnCpy(p+5,my_name,16);
  2395. +  strupper(p+5);
  2396. +  CVAL(p,21) = 2; /* major version */
  2397. +  CVAL(p,22) = 0; /* minor version */
  2398. +  stypep = p+23;
  2399. +  SIVAL(p,23,ServerType);
  2400. +  SSVAL(p,27,0xaa55); /* browse signature */
  2401. +  SSVAL(p,29,1); /* browse version */
  2402. +  commentp = p+31;
  2403. +  strcpy(p+31,comment);
  2404. +  p += 31;
  2405. +  p = skip_string(p,1);
  2406. +
  2407. +  send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  2408. +         my_name,d->name,0,0x1d,d->bcast_ip,myip);
  2409. +
  2410. +  /* if I'm the master then I also need to do a local master and
  2411. +     domain announcement */
  2412. +
  2413. +  if (AM_MASTER &&
  2414. +      strequal(d->name,PrimaryGroup) &&
  2415. +      ip_equal(bcast_ip,d->bcast_ip)) {
  2416. +
  2417. +    /* do master announcements as well */
  2418. +
  2419. +    CVAL(outbuf,0) = 15; /* local master announce */
  2420. +    send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  2421. +           my_name,PrimaryGroup,0,0x1e,d->bcast_ip,myip);
  2422. +
  2423. +    CVAL(outbuf,0) = 12; /* domain announce */
  2424. +    StrnCpy(namep,PrimaryGroup,15);
  2425. +    strupper(namep);
  2426. +    StrnCpy(commentp,myname,15);
  2427. +    strupper(commentp);
  2428. +    SIVAL(stypep,0,(unsigned)0x80000000);
  2429. +    p = commentp + strlen(commentp) + 1;
  2430.  
  2431. -  return;
  2432. +    send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  2433. +           my_name,MSBROWSE,0,1,d->bcast_ip,myip);
  2434. +  }
  2435.  }
  2436.  
  2437. +
  2438.  /****************************************************************************
  2439. -reply to a name release
  2440. -****************************************************************************/
  2441. -static void reply_name_release(char *inbuf)
  2442. +  send a announce request to the local net
  2443. +  **************************************************************************/
  2444. +static void announce_request(char *group)
  2445.  {
  2446.    pstring outbuf;
  2447. -  int rec_name_trn_id = RSVAL(inbuf,0);
  2448. -  char qname[100]="";
  2449. -  char *p = inbuf;
  2450. -  struct in_addr ip;
  2451. -  int n=0;
  2452. -  int name_type;
  2453. -  unsigned char nb_flags;
  2454. -  struct in_addr tmpip;
  2455. -  BOOL release_ok=False;
  2456. -  int reason=5;
  2457. +  char *p;
  2458.  
  2459. +  DEBUG(2,("Sending announce request to %s for workgroup %s\n",
  2460. +       inet_ntoa(bcast_ip),group));
  2461.  
  2462.    bzero(outbuf,sizeof(outbuf));
  2463. -
  2464. -  name_type = name_extract(inbuf,12,qname);
  2465. +  p = outbuf;
  2466. +  CVAL(p,0) = 2; /* announce request */
  2467. +  p++;
  2468.  
  2469. -  p += 12;
  2470. -  p += name_len(p);
  2471. -  p += 4;
  2472. -  p += name_len(p);
  2473. -  p += 4;
  2474. -  nb_flags = CVAL(p,6);
  2475. -  p += 8;
  2476. -  putip((char *)&ip,p);
  2477. -
  2478. -  DEBUG(2,("Name release request for %s (%s) nb_flags=0x%x ntype=%d\n",
  2479. -    qname,inet_ntoa(ip),nb_flags,name_type));
  2480. -
  2481. -  n = find_name(qname,name_type,True);
  2482. -  if (n>=0 && names[n].source == REGISTER &&
  2483. -      !memcmp((char *)&ip,(char *)&names[n].ip,sizeof(ip))) {
  2484. -    release_ok = True;
  2485. -    names[n].valid = False;
  2486. -  }
  2487. -
  2488. -  /* Send a POSITIVE NAME RELEASE RESPONSE */
  2489. -  RSSVAL(outbuf,0,rec_name_trn_id);
  2490. -  CVAL(outbuf,2) = (1<<7) | (6<<3) | 4;
  2491. -  CVAL(outbuf,3) = release_ok?0:reason;
  2492. -  RSSVAL(outbuf,4,0);
  2493. -  RSSVAL(outbuf,6,1);
  2494. -  RSSVAL(outbuf,8,0);
  2495. -  RSSVAL(outbuf,10,0);  
  2496. -  p = outbuf+12;
  2497. -  strcpy(p,inbuf+12);
  2498. -  p += name_len(p);
  2499. -  RSSVAL(p,0,0x20);
  2500. -  RSSVAL(p,2,0x1);
  2501. -  RSIVAL(p,4,0); /* ttl */
  2502. -  RSSVAL(p,8,6);
  2503. -  RSSVAL(p,10,nb_flags);
  2504. -  p += 12;
  2505. -  putip(p,&ip);  
  2506. -  p += 4;
  2507. -
  2508. -  DEBUG(2,("Sending a %s name release response\n",release_ok?"positive":"negative"));
  2509. -  if (DEBUGLEVEL > 2)
  2510. -    show_nmb(outbuf);
  2511. -
  2512. -  tmpip = lastip;
  2513. -  num_good_sends++;
  2514. -  send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
  2515. +  CVAL(p,0) = 0; /* flags?? */
  2516. +  p++;
  2517. +  StrnCpy(p,myname,16);
  2518. +  strupper(p);
  2519. +  p = skip_string(p,1);
  2520.  
  2521. -  return;
  2522. +  send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  2523. +         myname,group,0,0,bcast_ip,myip);
  2524.  }
  2525.  
  2526.  
  2527. -/****************************************************************************
  2528. -reply to a name status query
  2529. -****************************************************************************/
  2530. -static void reply_name_status(char *inbuf)
  2531. -{
  2532. -  pstring outbuf;
  2533. -  fstring qname;
  2534. -  int rec_name_trn_id = RSVAL(inbuf,0);
  2535. -  char *p = inbuf;
  2536. -  struct in_addr tmpip;
  2537. -  int i;
  2538. -  int count=0;
  2539. -  int name_type;
  2540. -  BOOL wildcard = False;
  2541. -
  2542. -  bzero(outbuf,sizeof(outbuf));
  2543. -
  2544. -  name_type = name_extract(inbuf,12,qname);
  2545. -  wildcard = (qname[0]=='*');
  2546. +/*******************************************************************
  2547. +  am I listening on a name. Should check name_type as well 
  2548.  
  2549. -  DEBUG(2,("(%s) status query on name (%s)\n",inet_ntoa(lastip), qname));
  2550. +  This is primarily used to prevent us gathering server lists from
  2551. +  other workgroups we aren't a part of
  2552. +  ******************************************************************/
  2553. +static BOOL listening(struct nmb_name *n)
  2554. +{
  2555. +  if (!strequal(n->scope,scope)) return(False);
  2556. +
  2557. +  if (strequal(n->name,myname) ||
  2558. +      strequal(n->name,PrimaryGroup) ||
  2559. +      strequal(n->name,MSBROWSE))
  2560. +    return(True);
  2561.  
  2562. -  if (!wildcard) {
  2563. -    i = find_name(qname,name_type,False);
  2564. +  return(False);
  2565. +}
  2566.  
  2567. -    if (i < 0)
  2568. -      return;
  2569. -    if (names[i].source != SELF && names[i].source != LMHOSTS)
  2570. -      return;
  2571. -  }
  2572.  
  2573. -  /* Send a POSITIVE NAME STATUS RESPONSE */
  2574. -  RSSVAL(outbuf,0,rec_name_trn_id);
  2575. -  CVAL(outbuf,2) = (1<<7) | (1<<2);
  2576. -  CVAL(outbuf,3) = 0;
  2577. -  RSSVAL(outbuf,4,0);
  2578. -  RSSVAL(outbuf,6,1);
  2579. -  RSSVAL(outbuf,8,0);
  2580. -  RSSVAL(outbuf,10,0);  
  2581. -  p = outbuf+12;
  2582. -  strcpy(p,inbuf+12);
  2583. -  p += name_len(p);
  2584. -  RSSVAL(p,0,0x21);
  2585. -  RSSVAL(p,2,0x1);
  2586. -  RSIVAL(p,4,0);
  2587. -  RSSVAL(p,8,6);
  2588. -  p += 10;
  2589. -
  2590. -  for (i=0;i<num_names;i++)
  2591. -    if (names[i].valid) count++;
  2592. -  count = MIN(count,(512 - (46 + 1 + PTR_DIFF(p,outbuf)))/18);
  2593. +/*******************************************************************
  2594. +  process a domain announcement frame
  2595.  
  2596. -  SCVAL(p,0,count);
  2597. -  p++;
  2598. +  Announce frames come in 3 types. Servers send host announcements
  2599. +  (command=1) to let the master browswer know they are
  2600. +  available. Master browsers send local master announcements
  2601. +  (command=15) to let other masters and backups that they are the
  2602. +  master. They also send domain announcements (command=12) to register
  2603. +  the domain
  2604. +
  2605. +  The comment field of domain announcements contains the master
  2606. +  browser name. The servertype is used by NetServerEnum to select
  2607. +  resources. We just have to pass it to smbd (via browser.dat) and let
  2608. +  the client choose using bit masks.
  2609. +  ******************************************************************/
  2610. +static void process_announce(struct packet_struct *p,int command,char *buf)
  2611. +{
  2612. +  struct dgram_packet *dgram = &p->packet.dgram;
  2613. +  int update_count = CVAL(buf,0);
  2614. +  int ttl = IVAL(buf,1)/1000;
  2615. +  char *name = buf+5;
  2616. +  int major=CVAL(buf,21);
  2617. +  int minor=CVAL(buf,22);
  2618. +  uint32 servertype = IVAL(buf,23);
  2619. +  char *comment = buf+31;
  2620. +
  2621. +  name[15] = 0;  
  2622. +  comment[43] = 0;
  2623. +  
  2624. +  DEBUG(3,("Announce(%d) %s count=%d ttl=%d OS=(%d,%d) type=%08x comment=%s\n",
  2625. +       command,name,update_count,ttl,major,minor,
  2626. +       servertype,comment));
  2627.  
  2628. -  for (i=0;i<num_names && count>0;i++)
  2629. -    if (names[i].valid)
  2630. -      {
  2631. -    bzero(p,18);
  2632. -    strcpy(p,names[i].name);
  2633. -    strupper(p);
  2634. -    p[15] = names[i].type;
  2635. -    p += 16;
  2636. -    p[0] = 0x4; /* active */
  2637. -    if (strequal(names[i].name,myname)) p[0] |= 0x2; /* permanent */
  2638. -    if (ISGROUP(i)) p[0] |= 0x80; /* group */
  2639. -    p += 2;
  2640. -    count--;
  2641. -      }
  2642. +  if (strequal(dgram->source_name.name,myname)) return;
  2643.  
  2644. -  bzero(p,46);
  2645. -  putip(p,(char *)&myip);
  2646. -  SIVAL(p,20,num_good_sends);
  2647. -  SIVAL(p,24,num_good_receives);
  2648. -  
  2649. -  p += 46;
  2650. -
  2651. -  tmpip = lastip;
  2652. -  num_good_sends++;
  2653. -  send_nmb(outbuf,PTR_DIFF(p,outbuf),&tmpip,lastport>0?lastport:137);
  2654. +  if (!listening(&dgram->dest_name)) return;
  2655.  
  2656. -  return;
  2657. +  /* add them to our browse list */
  2658. +  add_server_entry(name,servertype,ttl,comment);
  2659.  }
  2660.  
  2661.  
  2662. -/****************************************************************************
  2663. -reply to a name query
  2664. -****************************************************************************/
  2665. -static void reply_name_query(char *inbuf)
  2666. -{
  2667. -  pstring outbuf;
  2668. -  int rec_name_trn_id = RSVAL(inbuf,0);
  2669. -  char qname[100]="";
  2670. -  char *p = inbuf;
  2671. -  unsigned char nb_flags = 0;
  2672. -  int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  2673. -  struct in_addr tmpip;
  2674. -  struct in_addr retip;
  2675. -  int i=-1;
  2676. -  BOOL broadcast = ((nm_flags&1) != 0);
  2677. -  int name_type;
  2678. -  int qtype;
  2679. -  BOOL wildcard=False;
  2680. +/*******************************************************************
  2681. +  process a backup list request
  2682.  
  2683. -  bzero(outbuf,sizeof(outbuf));
  2684. +  A client send a backup list request to ask for a list of servers on
  2685. +  the net that maintain server lists for a domain. A server is then
  2686. +  chosen from this list to send NetServerEnum commands to to list
  2687. +  available servers.
  2688.  
  2689. -  name_type = name_extract(inbuf,12,qname);
  2690. +  Currently samba only sends back one name in the backup list, its
  2691. +  wn. For larger nets we'll have to add backups and send "become
  2692. +  backup" requests occasionally.
  2693. +  ******************************************************************/
  2694. +static void process_backup_list(struct packet_struct *p,char *buf)
  2695. +{
  2696. +  struct dgram_packet *dgram = &p->packet.dgram;
  2697. +  int count = CVAL(buf,0);
  2698. +  int token = IVAL(buf,1);
  2699. +  
  2700. +  DEBUG(3,("Backup request to %s token=%d\n",
  2701. +       namestr(&dgram->dest_name),
  2702. +       token));
  2703.  
  2704. -  wildcard = (qname[0] == '*');
  2705. +  if (strequal(dgram->source_name.name,myname)) return;
  2706.  
  2707. -  qtype = RSVAL(inbuf+12+name_len(inbuf+12),0);
  2708. +  if (count <= 0) return;
  2709.  
  2710. -  if (qtype == 0x21) {
  2711. -    reply_name_status(inbuf);
  2712. +  if (!AM_MASTER || 
  2713. +      !strequal(PrimaryGroup,dgram->dest_name.name))
  2714.      return;
  2715. -  }
  2716.  
  2717. -  if (qtype != 0x20) 
  2718. -    return;
  2719. +  if (!listening(&dgram->dest_name)) return;
  2720.  
  2721. -  DEBUG(2,("(%s) querying name (%s)(%d) (%s)",
  2722. -       inet_ntoa(lastip), qname, name_type,
  2723. -       broadcast?"BROADCAST":"UNICAST"));
  2724. +  send_backup_list(myname,token,
  2725. +           &dgram->source_name,
  2726. +           p->ip);
  2727. +}
  2728.  
  2729. -  if (!wildcard) {
  2730. -    i = find_name(qname,name_type,False);
  2731.  
  2732. -    if (i < 0)
  2733. -      i = find_name(qname,name_type,True);
  2734. -    
  2735. -    if (i >= 0)
  2736. -      {
  2737. -    if (broadcast && (names[i].unicast || names[i].source == REGISTER)) {
  2738. -      DEBUG(2,(" - broadcast. No reply\n"));
  2739. -      return;
  2740. -    }
  2741. +/*******************************************************************
  2742. +  work out if I win an election
  2743. +  ******************************************************************/
  2744. +static BOOL win_election(int version,uint32 criterion,int timeup,char *name)
  2745. +{  
  2746. +  time_t t = time(NULL);
  2747. +  uint32 mycriterion;
  2748. +  if (version > ELECTION_VERSION) return(False);
  2749. +  if (version < ELECTION_VERSION) return(True);
  2750.    
  2751. -    if (ISGROUP(i)) {
  2752. -      DEBUG(2,(" - group name. No reply\n"));
  2753. -      return;
  2754. -    }
  2755. +  mycriterion = ElectionCriterion;
  2756.  
  2757. -    retip = names[i].ip;
  2758. -    DEBUG(2,(" sending positive reply\n"));
  2759. -      }
  2760. -    else
  2761. -      {
  2762. -    if ((name_type!=0 && name_type!=0x3 && name_type!=0x20) ||
  2763. -        (broadcast && !dns_serve))
  2764. -      {
  2765. -        DEBUG(2,("\n"));
  2766. -        return;
  2767. -      }
  2768. -    else
  2769. -      /* try a DNS query to get the IP */
  2770. -      {
  2771. -        struct hostent *hp;
  2772. -        pstring hname;
  2773. -        
  2774. -        StrnCpy(hname,qname,15);
  2775. -        trim_string(hname," "," ");
  2776. -        trim_string(hname,".",".");
  2777. -        p = strchr(hname,' ');
  2778. -        if (p) *p = 0;
  2779. -        
  2780. -        if ((hp = Get_Hostbyname(hname)) == 0) 
  2781. -          {
  2782. -        DEBUG(2,(": unknown name sending no reply\n"));
  2783. -        return;
  2784. -          }
  2785. -        
  2786. -        putip((char *)&retip,(char *)hp->h_addr);
  2787. -        
  2788. -        if (broadcast && is_mynet(retip)) {
  2789. -          DEBUG(2,(" on same subnet (%s), no reply\n",inet_ntoa(retip)));
  2790. -          return;
  2791. -        }
  2792. -        i = find_name(qname,name_type,True);
  2793. -        if (i < 0) {
  2794. -          if ((i=add_name())>=0) {
  2795. -        StrnCpy(names[i].name,qname,15);
  2796. -        names[i].type = name_type;
  2797. -        names[i].unicast = is_mynet(retip);
  2798. -        names[i].ip = retip;
  2799. -        names[i].valid = True;
  2800. -        names[i].ttl = 120; /* give it two minutes */
  2801. -        names[i].start_time = time(NULL);
  2802. -        names[i].source = DNS;        
  2803. -          }
  2804. -        }
  2805. -      }
  2806. -    DEBUG(2,(" sending positive reply (%s)\n",inet_ntoa(retip)));
  2807. -      }
  2808. -  } else {
  2809. -    retip = myip;
  2810. -  }
  2811. -  
  2812. -  /* Send a POSITIVE NAME QUERY RESPONSE */
  2813. -  RSSVAL(outbuf,0,rec_name_trn_id);
  2814. -  CVAL(outbuf,2) = (1<<7) | 0x5;
  2815. -  CVAL(outbuf,3) = 0;
  2816. -  RSSVAL(outbuf,4,0);
  2817. -  RSSVAL(outbuf,6,1);
  2818. -  RSSVAL(outbuf,8,0);
  2819. -  RSSVAL(outbuf,10,0);  
  2820. -  p = outbuf+12;
  2821. -  strcpy(p,inbuf+12);
  2822. -  p += name_len(p);
  2823. -  RSSVAL(p,0,0x20);
  2824. -  RSSVAL(p,2,0x1);
  2825. -  RSIVAL(p,4,0); /* my ttl ? */
  2826. -  RSSVAL(p,8,6);
  2827. -  CVAL(p,10) = nb_flags;
  2828. -  CVAL(p,11) = 0;
  2829. -  p += 12;
  2830. -  putip(p,(char *)&retip);
  2831. -  p += 4;
  2832. -
  2833. -  show_nmb(outbuf);
  2834. -
  2835. -  tmpip = lastip;
  2836. -  num_good_sends++;
  2837. -  send_nmb(outbuf,nmb_len(outbuf),&tmpip,lastport>0?lastport:137);
  2838. +  if (criterion > mycriterion) return(False);
  2839. +  if (criterion < mycriterion) return(True);
  2840.  
  2841. -  return;
  2842. +  if (timeup > (t - StartupTime)) return(False);
  2843. +  if (timeup < (t - StartupTime)) return(True);
  2844. +
  2845. +  if (strcasecmp(myname,name) > 0) return(False);
  2846. +  
  2847. +  return(True);
  2848.  }
  2849.  
  2850.  
  2851. +/*******************************************************************
  2852. +  process a election packet
  2853.  
  2854. -/****************************************************************************
  2855. -  construct a reply to the incoming packet
  2856. -****************************************************************************/
  2857. -void construct_reply(char *inbuf)
  2858. +  An election dynamically decides who will be the master. 
  2859. +  ******************************************************************/
  2860. +static void process_election(struct packet_struct *p,char *buf)
  2861.  {
  2862. -  int opcode = CVAL(inbuf,2) >> 3;
  2863. -  int nm_flags = ((CVAL(inbuf,2) & 0x7) << 4) + (CVAL(inbuf,3)>>4);
  2864. -  int rcode = CVAL(inbuf,3) & 0xF;
  2865. -  int bcast = (nm_flags&1);
  2866. -  int response = (CVAL(inbuf,2)>>7);
  2867. -  int qdcount = RSVAL(inbuf,4);
  2868. -  int arcount = RSVAL(inbuf,10);
  2869. +  struct dgram_packet *dgram = &p->packet.dgram;
  2870. +  int version = CVAL(buf,0);
  2871. +  uint32 criterion = IVAL(buf,1);
  2872. +  int timeup = IVAL(buf,5)/1000;
  2873. +  char *name = buf+13;
  2874.  
  2875. -  /* if this is a response then ignore it */
  2876. -  if (response || rcode) return;
  2877. +  name[15] = 0;  
  2878.    
  2879. -  if (!bcast && opcode == 0x5 && qdcount==1 && arcount==1)
  2880. -    {
  2881. -      reply_name_reg(inbuf);
  2882. -      return;
  2883. -    }
  2884. +  DEBUG(3,("Election request from %s vers=%d criterion=%08x timeup=%d\n",
  2885. +       name,version,criterion,timeup));
  2886.  
  2887. -  if (opcode == 0 && qdcount==1)
  2888. -    {
  2889. -      reply_name_query(inbuf);
  2890. -      return;
  2891. -    }
  2892. +  if (strequal(dgram->source_name.name,myname)) return;
  2893.  
  2894. -  if (!bcast && opcode == 6 && qdcount==1 && arcount==1)
  2895. -    {
  2896. -      reply_name_release(inbuf);
  2897. -      return;
  2898. -    }
  2899. +  if (!listening(&dgram->dest_name)) return;
  2900.  
  2901. -  if (!bcast && ((opcode == 8) || (opcode == 9)) && qdcount==1 && arcount==1)
  2902. -    {
  2903. -      reply_name_reg(inbuf);
  2904. -      return;
  2905. +  if (win_election(version,criterion,timeup,name)) {
  2906. +    if (!RunningElection) {
  2907. +      needelection = True;
  2908. +      ElectionCount=0;
  2909. +    }
  2910. +  } else {
  2911. +    needelection = False;
  2912. +    if (RunningElection) {
  2913. +      RunningElection = False;
  2914. +      DEBUG(3,(">>> Lost election on %s <<<\n",PrimaryGroup));
  2915. +
  2916. +      /* if we are the master then remove our masterly names */
  2917. +      if (AM_MASTER)
  2918. +    become_nonmaster();
  2919.      }
  2920. +  }
  2921.  }
  2922.  
  2923.  
  2924. -/****************************************************************************
  2925. -construct a host announcement unicast
  2926. -****************************************************************************/
  2927. -static BOOL send_udp_138(char *buf,int len,
  2928. -             char *srcname,char *dstname,
  2929. -             int src_type,int dest_type,
  2930. -             struct in_addr dest_ip)
  2931. +/*******************************************************************
  2932. +  process a announcement request
  2933. +
  2934. +  clients send these when they want everyone to send an announcement
  2935. +  immediately. This can cause quite a storm of packets!
  2936. +  ******************************************************************/
  2937. +static void process_announce_request(struct packet_struct *p,char *buf)
  2938.  {
  2939. -  pstring outbuf;
  2940. -  char *p,*p2;
  2941. -  static int id=0;
  2942. -  char tmp[4];
  2943. -  struct sockaddr_in sock_out;
  2944. +  struct dgram_packet *dgram = &p->packet.dgram;
  2945. +  int flags = CVAL(buf,0);
  2946. +  char *name = buf+1;
  2947.  
  2948. -  bzero(outbuf,sizeof(outbuf));
  2949. -  RSSVAL(outbuf,0,0x1102); /* what is this? */
  2950. -  RSSVAL(outbuf,2,++id); 
  2951. -  putip(outbuf+4,(void *)&myip);
  2952. -  RSSVAL(outbuf,8,138);
  2953. -  RSSVAL(outbuf,12,0);
  2954. -  p = outbuf + 14;
  2955. -  p += name_mangle(srcname,p,src_type);
  2956. -  p += name_mangle(dstname,p,dest_type);
  2957. -
  2958. -  /* now setup the smb part */
  2959. -  p -= 4;
  2960. -  memcpy(tmp,p,4);
  2961. -  set_message(p,17,17 + len,True);
  2962. -  memcpy(p,tmp,4);
  2963. -
  2964. -  CVAL(p,smb_com) = SMBtrans;
  2965. -  SSVAL(p,smb_vwv1,len);
  2966. -  SSVAL(p,smb_vwv11,len);
  2967. -  SSVAL(p,smb_vwv12,86);
  2968. -  SSVAL(p,smb_vwv13,3);
  2969. -  SSVAL(p,smb_vwv14,1);
  2970. -  SSVAL(p,smb_vwv15,1);
  2971. -  SSVAL(p,smb_vwv16,2);
  2972. -  p2 = smb_buf(p);
  2973. -  strcpy(p2,"\\MAILSLOT\\BROWSE");
  2974. -  p2 = skip_string(p2,1);
  2975. -
  2976. -  memcpy(p2,buf,len);
  2977. -  p2 += len;
  2978. -
  2979. -  len = PTR_DIFF(p2,outbuf);
  2980. -  RSSVAL(outbuf,10,len);
  2981. -
  2982. -
  2983. -  /* set the address and port */
  2984. -  bzero((char *)&sock_out,sizeof(sock_out));
  2985. -  putip((char *)&sock_out.sin_addr,(char *)&dest_ip);
  2986. -  sock_out.sin_port = htons(138);
  2987. -  sock_out.sin_family = AF_INET;
  2988. -  
  2989. -  /* log the packet */
  2990. -  log_out(outbuf,len);
  2991. -  
  2992. -  /* send it */
  2993. -  if (sendto(Client138,outbuf,len,0,
  2994. -         (struct sockaddr *)&sock_out,sizeof(sock_out)) < 0) {
  2995. -    DEBUG(3,("Sendto failed errno=%d (%s)\n",errno,strerror(errno)));
  2996. -    return(False);
  2997. -  } else {
  2998. -    num_good_sends++;
  2999. -  }
  3000. -  return(True);
  3001. +  name[15] = 0;
  3002. +
  3003. +  DEBUG(3,("Announce request from %s flags=0x%X\n",name,flags));
  3004. +
  3005. +  if (strequal(dgram->source_name.name,myname)) return;
  3006. +
  3007. +  needannounce = True;
  3008.  }
  3009.  
  3010. +
  3011.  /****************************************************************************
  3012. -construct a host announcement unicast
  3013. +process a browse frame
  3014.  ****************************************************************************/
  3015. -static void announce_host(int i,char *my_name,char *Comment)
  3016. +static void process_browse_packet(struct packet_struct *p,char *buf,int len)
  3017.  {
  3018. -  static int announce_interval = 1;
  3019. -  char *group = names[i].name;
  3020. -  struct in_addr dest_ip = names[i].ip;
  3021. -  pstring outbuf;
  3022. -  char *p;
  3023. +  int command = CVAL(buf,0);
  3024. +  switch (command) 
  3025. +    {
  3026. +    case 1: /* host announce */
  3027. +    case 12: /* domain announce */
  3028. +    case 15: /* local master announce */
  3029. +      process_announce(p,command,buf+1);
  3030. +      break;
  3031.  
  3032. -  names[i].count++;
  3033. +    case 2: /* announce request */
  3034. +      process_announce_request(p,buf+1);
  3035. +      break;
  3036.  
  3037. -  if ((names[i].count % announce_interval) != 0) return;
  3038. +    case 8: /* election */
  3039. +      process_election(p,buf+1);
  3040. +      break;
  3041.  
  3042. -  if (announce_interval < 2) announce_interval++;
  3043. +    case 9: /* get backup list */
  3044. +      process_backup_list(p,buf+1);
  3045. +      break;
  3046. +    }
  3047. +}
  3048.  
  3049. -  DEBUG(2,("Sending host announcement to %s for group %s\n",
  3050. -       inet_ntoa(dest_ip),group));       
  3051.  
  3052. -  if (!*Comment) Comment = "NoComment";
  3053. -  if (!*my_name) my_name = "NoName";
  3054. -  if (!*group) group = "NoGroup";
  3055. +/****************************************************************************
  3056. +process udp 138 datagrams
  3057. +****************************************************************************/
  3058. +static void process_dgram(struct packet_struct *p)
  3059. +{
  3060. +  char *buf;
  3061. +  char *buf2;
  3062. +  int len;
  3063. +  struct dgram_packet *dgram = &p->packet.dgram;
  3064.  
  3065. -  if (strlen(Comment) > 47) Comment[47] = 0;  
  3066. +  if (dgram->header.msg_type != 0x10 &&
  3067. +      dgram->header.msg_type != 0x11 &&
  3068. +      dgram->header.msg_type != 0x12) {
  3069. +    /* don't process error packets etc yet */
  3070. +    return;
  3071. +  }
  3072.  
  3073. -  bzero(outbuf,sizeof(outbuf));
  3074. -  p = outbuf;
  3075. -  CVAL(p,0) = 1; /* host announce */
  3076. -  SSVAL(p,1,0x6006); /* update count?? */
  3077. -  CVAL(p,3) = 0xEA; /* res1 */ 
  3078. -  SSVAL(p,4,announce_interval);
  3079. -  p += 6;
  3080. -  StrnCpy(p,my_name,16);
  3081. -  strupper(p);
  3082. -  p += 16;
  3083. -  CVAL(p,0) = 1; /* major version (was 1) */
  3084. -  CVAL(p,1) = 0x33; /* minor version (was 51) */
  3085. -  SIVAL(p,2,0xB03); /* server and w'station + unix + printq + domain member*/
  3086. -  SSVAL(p,6,0x30B); /* election version */
  3087. -  SSVAL(p,8,0xAA55); /* browse constant */
  3088. -  p += 10;
  3089. -  strcpy(p,Comment);
  3090. -  p += strlen(p)+1;
  3091. +  buf = &dgram->data[0];
  3092. +  buf -= 4; /* XXXX for the pseudo tcp length - 
  3093. +           someday I need to get rid of this */
  3094.  
  3095. -  send_udp_138(outbuf,PTR_DIFF(p,outbuf),my_name,group,0,0x1d,dest_ip);
  3096. -}
  3097. +  if (CVAL(buf,smb_com) != SMBtrans) return;
  3098.  
  3099. +  len = SVAL(buf,smb_vwv11);
  3100. +  buf2 = smb_base(buf) + SVAL(buf,smb_vwv12);
  3101.  
  3102. +  DEBUG(3,("datagram from %s to %s for %s of type %d len=%d\n",
  3103. +       namestr(&dgram->source_name),namestr(&dgram->dest_name),
  3104. +       smb_buf(buf),CVAL(buf2,0),len));
  3105.  
  3106. -/****************************************************************************
  3107. -send a name registration packet
  3108. -****************************************************************************/
  3109. -static void send_registration(char *name,int name_type,struct in_addr dest_ip,struct in_addr ip,BOOL refresh,int ttl)
  3110. -{
  3111. -  char *p;
  3112. -  static int t = 0x176;
  3113. -  pstring outbuf;
  3114. -  bzero(outbuf,sizeof(outbuf));
  3115. -  /* send a registration request */
  3116. -  RSSVAL(outbuf,0,t++);
  3117. -  if (refresh)
  3118. -    CVAL(outbuf,2) = (0<<7) | (9<<3) | 0;
  3119. -  else
  3120. -    CVAL(outbuf,2) = (0<<7) | (5<<3) | 1;
  3121. -    
  3122. -  CVAL(outbuf,3) = (1<<4);
  3123. -  RSSVAL(outbuf,4,1);
  3124. -  RSSVAL(outbuf,6,0);
  3125. -  RSSVAL(outbuf,8,0);
  3126. -  RSSVAL(outbuf,10,1);  
  3127. -  p = outbuf+12;
  3128. -  name_mangle(name,p,name_type);
  3129. -  p += name_len(p);
  3130. -  RSSVAL(p,0,0x20);
  3131. -  RSSVAL(p,2,0x1);
  3132. -  p += 4;
  3133. -  RSSVAL(p,0,12);
  3134. -  CVAL(p,0) = CVAL(p,0) | 0xC0;
  3135. -  p += 2;
  3136. -  RSSVAL(p,0,0x20);
  3137. -  RSSVAL(p,2,0x1);
  3138. -  p += 4;  
  3139. -  RSIVAL(p,0,ttl);
  3140. -
  3141. -  RSSVAL(p,4,6);
  3142. -  RSSVAL(p,6,0);  
  3143. -  p += 8;
  3144. -  putip(p,&ip);  
  3145. -  p += 4;
  3146. -
  3147. -  DEBUG(2,("Sending a name registration request\n"));
  3148. -  if (DEBUGLEVEL > 2)
  3149. -    show_nmb(outbuf);
  3150. +  /* only understand browse datagrams */
  3151. +  if (!strequal(smb_buf(buf),"\\MAILSLOT\\BROWSE"))
  3152. +    return;
  3153.  
  3154. -  num_good_sends++;
  3155. -  send_nmb(outbuf,PTR_DIFF(p,outbuf),&dest_ip,137);
  3156. +  if (len <= 0) return;
  3157. +  process_browse_packet(p,buf2,len);
  3158.  }
  3159.  
  3160.  /*******************************************************************
  3161. -find a master browser
  3162. -********************************************************************/
  3163. -BOOL find_master(char *name1,struct in_addr ip,struct in_addr *ipout,
  3164. -         void (*fn)())
  3165. +  find a workgroup using the specified broadcast
  3166. +  ******************************************************************/
  3167. +static BOOL find_workgroup(char *name,struct in_addr ip)
  3168.  {
  3169. -  int type = 0x1d;
  3170. -  fstring name;
  3171. +  fstring name1;
  3172.    BOOL ret;
  3173. -  strcpy(name,name1);
  3174. -  if (strequal(name,"*")) {
  3175. -    strcpy(name,"\001\002__MSBROWSE__\002");
  3176. -    type = 1;
  3177. -  }
  3178. -  ret = name_query(name,type,True,ip,ipout,fn);
  3179. +  struct in_addr ipout;
  3180. +
  3181. +  strcpy(name1,MSBROWSE);
  3182. +
  3183. +  ret = name_query(ClientNMB,name1,0x1,True,False,ip,&ipout,queue_packet);
  3184.    if (!ret) return(False);
  3185. -  if (type != 1) return(True);
  3186.  
  3187. -  name_status(name,type,*ipout,fn,name1);
  3188. -  return(name1[0] != '*');
  3189. +  name_status(ClientNMB,name1,0x1,False,ipout,name,queue_packet);
  3190. +
  3191. +  if (name[0] != '*') {
  3192. +    DEBUG(2,("Found workgroup %s on broadcast %s\n",name,inet_ntoa(ip)));
  3193. +  } else {
  3194. +    DEBUG(3,("Failed to find workgroup %s on broadcast %s\n",name,inet_ntoa(ip)));
  3195. +  }
  3196. +  return(name[0] != '*');
  3197.  }
  3198.  
  3199. +
  3200.  /****************************************************************************
  3201. -process a workgroup announce frame
  3202. -****************************************************************************/
  3203. -static void process_workgroup_announce(char *group,struct in_addr ip)
  3204. +  a hook for announce handling - called every minute
  3205. +  **************************************************************************/
  3206. +static void do_announcements(void)
  3207.  {
  3208. -  int i;
  3209. -  for (i=0;i<num_names;i++)
  3210. -    if (names[i].valid) {
  3211. -      if (names[i].name[0] == '*') {
  3212. -    StrnCpy(names[i].name,group,15);
  3213. -    names[i].master_ip = ip;
  3214. -    names[i].found_master = True;
  3215. -    names[i].count=0;
  3216. -    announce_host(i,myname,comment);
  3217. -    return;
  3218. -      }
  3219. -      if (names[i].isgroup && name_equal(names[i].name,group,0,0)) {
  3220. -    int j;
  3221. -    for (j=i;j<num_names;j++)
  3222. -      if (names[j].valid && names[j].isgroup && names[i].found_master && 
  3223. -          name_equal(names[i].name,group,0,0)) return;
  3224. -    names[i].master_ip = ip;
  3225. -    names[i].found_master = True;
  3226. -    names[i].count=0;
  3227. -    announce_host(i,myname,comment);
  3228. -    return;
  3229. +  struct domain_record *d;
  3230. +
  3231. +  for (d = domainlist; d; d = d->next) {
  3232. +    /* if the ip address is 0 then set to the broadcast */
  3233. +    if (zero_ip(d->bcast_ip)) d->bcast_ip = bcast_ip;
  3234. +
  3235. +    /* if the workgroup is '*' then find a workgroup to be part of */
  3236. +    if (d->name[0] == '*') {
  3237. +      if (!find_workgroup(d->name,d->bcast_ip)) continue;
  3238. +      add_host_entry(d->name,0x1e,False,0,SELF,
  3239. +             *interpret_addr2("255.255.255.255"));
  3240. +      if (!*PrimaryGroup && ip_equal(bcast_ip,d->bcast_ip)) {
  3241. +    strcpy(PrimaryGroup,d->name);
  3242. +    strupper(PrimaryGroup);
  3243.        }
  3244.      }
  3245. +
  3246. +    announce_host(d,myname,ServerComment);
  3247. +  }
  3248. +
  3249. +  needannounce=False;
  3250.  }
  3251.  
  3252. +/*******************************************************************
  3253. +  check if someone still owns a name
  3254. +  ******************************************************************/
  3255. +static BOOL confirm_name(struct name_record *n)
  3256. +{
  3257. +  struct in_addr ipout;
  3258. +  BOOL ret = name_query(ClientNMB,n->name.name,
  3259. +            n->name.name_type,False,
  3260. +            False,n->ip,&ipout,queue_packet);
  3261. +  return(ret && ip_equal(ipout,n->ip));
  3262. +}
  3263.  
  3264.  /****************************************************************************
  3265. -process a browse frame
  3266. +reply to a name release
  3267.  ****************************************************************************/
  3268. -static void process_browse_packet(char *buf,int len)
  3269. +static void reply_name_release(struct packet_struct *p)
  3270.  {
  3271. -  char *p;
  3272. -  int command = CVAL(buf,0);
  3273. -  switch (command) {
  3274. -  case 0xc: /* workgroup announcement */
  3275. -    {
  3276. -      fstring group;
  3277. -      p = buf + 6;
  3278. -      StrnCpy(group,p,15);
  3279. -      DEBUG(2,("Got workgroup announce for %s (%s)\n",
  3280. -           group,inet_ntoa(lastip)));
  3281. -      process_workgroup_announce(group,lastip);
  3282. -      break;
  3283. +  struct nmb_packet *nmb = &p->packet.nmb;
  3284. +  struct packet_struct p2;
  3285. +  struct nmb_packet *nmb2;
  3286. +  struct res_rec answer_rec;
  3287. +  struct in_addr ip;
  3288. +  int rcode=0;
  3289. +  int nb_flags = nmb->additional->rdata[0];
  3290. +  BOOL bcast = nmb->header.nm_flags.bcast;
  3291. +  
  3292. +
  3293. +  putip((char *)&ip,&nmb->additional->rdata[2]);  
  3294. +
  3295. +  {
  3296. +    struct name_record *n = find_name(&nmb->question.question_name);
  3297. +    if (n && n->unique && n->source == REGISTER &&
  3298. +    ip_equal(ip,n->ip)) {
  3299. +      remove_name(n); n = NULL;
  3300.      }
  3301. +
  3302. +    /* XXXX under what conditions should we reject the removal?? */
  3303.    }
  3304.  
  3305. +  DEBUG(3,("Name release on name %s rcode=%d\n",
  3306. +       namestr(&nmb->question.question_name),rcode));
  3307. +
  3308. +  if (bcast) return;
  3309. +
  3310. +  /* Send a NAME RELEASE RESPONSE */
  3311. +  p2 = *p;
  3312. +  nmb2 = &p2.packet.nmb;
  3313. +
  3314. +  nmb2->header.response = True;
  3315. +  nmb2->header.nm_flags.bcast = False;
  3316. +  nmb2->header.nm_flags.recursion_available = CanRecurse;
  3317. +  nmb2->header.nm_flags.trunc = False;
  3318. +  nmb2->header.nm_flags.authoritative = True; 
  3319. +  nmb2->header.qdcount = 0;
  3320. +  nmb2->header.ancount = 1;
  3321. +  nmb2->header.nscount = 0;
  3322. +  nmb2->header.arcount = 0;
  3323. +  nmb2->header.rcode = rcode;
  3324. +
  3325. +  nmb2->answers = &answer_rec;
  3326. +  bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
  3327. +  
  3328. +  nmb2->answers->rr_name = nmb->question.question_name;
  3329. +  nmb2->answers->rr_type = nmb->question.question_type;
  3330. +  nmb2->answers->rr_class = nmb->question.question_class;
  3331. +  nmb2->answers->ttl = 0; 
  3332. +  nmb2->answers->rdlength = 6;
  3333. +  nmb2->answers->rdata[0] = nb_flags;
  3334. +  putip(&nmb2->answers->rdata[2],(char *)&ip);
  3335. +
  3336. +  send_packet(&p2);
  3337.  }
  3338.  
  3339.  /****************************************************************************
  3340. -process udp 138 datagrams
  3341. -****************************************************************************/
  3342. -static void process_138(void)
  3343. -{
  3344. -  pstring inbuf;
  3345. -  int len;
  3346. -  while (read_max_udp(Client138,inbuf,sizeof(inbuf),1) > 4) {
  3347. -    char *p = inbuf;
  3348. -    len = RSVAL(inbuf,10);
  3349. -    p += 14;
  3350. -    p += name_len(p);
  3351. -    p += name_len(p);
  3352. -    p -= 4;
  3353. -    if (CVAL(p,smb_com) != SMBtrans) continue;
  3354. -    if (!strequal(smb_buf(p),"\\MAILSLOT\\BROWSE")) continue;
  3355. -    len = SVAL(p,smb_vwv11);
  3356. -    p = smb_base(p) + SVAL(p,smb_vwv12);
  3357. -    if (len <= 0) continue;
  3358. -    process_browse_packet(p,len);
  3359. +  reply to a reg request
  3360. +  **************************************************************************/
  3361. +static void reply_name_reg(struct packet_struct *p)
  3362. +{
  3363. +  struct nmb_packet *nmb = &p->packet.nmb;
  3364. +  char *qname = nmb->question.question_name.name;
  3365. +  BOOL wildcard = (qname[0] == '*'); 
  3366. +  BOOL bcast = nmb->header.nm_flags.bcast;
  3367. +  int ttl = nmb->additional->ttl;
  3368. +  int name_type = nmb->question.question_name.name_type;
  3369. +  int nb_flags = nmb->additional->rdata[0];
  3370. +  struct packet_struct p2;
  3371. +  struct nmb_packet *nmb2;
  3372. +  struct res_rec answer_rec;
  3373. +  struct in_addr ip;
  3374. +  BOOL group = (nb_flags&0x80)?True:False;
  3375. +  int rcode = 0;  
  3376. +
  3377. +  if (wildcard) return;
  3378. +
  3379. +  putip((char *)&ip,&nmb->additional->rdata[2]);
  3380. +
  3381. +  if (group) {
  3382. +    /* apparently we should return 255.255.255.255 for group queries (email from MS) */
  3383. +    ip = *interpret_addr2("255.255.255.255");
  3384. +  }
  3385. +
  3386. +  {
  3387. +    struct name_record *n = find_name(&nmb->question.question_name);
  3388. +
  3389. +    if (n) {
  3390. +      if (!group && !ip_equal(ip,n->ip)) {
  3391. +    /* check if the previous owner still wants it, 
  3392. +       if so reject the registration, otherwise change the owner 
  3393. +       and refresh */
  3394. +    if (n->source != REGISTER || confirm_name(n)) {
  3395. +      rcode = 6;
  3396. +    } else {
  3397. +      n->ip = ip;
  3398. +      n->death_time = ttl?p->timestamp+ttl*3:0;
  3399. +      DEBUG(3,("%s changed owner to %s\n",
  3400. +           namestr(&n->name),inet_ntoa(n->ip)));
  3401. +    }
  3402. +      } else {
  3403. +    /* refresh the name */
  3404. +    if (n->source != SELF)
  3405. +      n->death_time = ttl?p->timestamp + ttl*3:0;
  3406. +      }
  3407. +    } else {
  3408. +      /* add the name to our database */
  3409. +      n = add_host_entry(qname,name_type,!group,ttl,REGISTER,ip);
  3410. +    }
  3411.    }
  3412. +
  3413. +  if (bcast) return;
  3414. +
  3415. +  DEBUG(3,("Name registration for name %s at %s rcode=%d\n",
  3416. +       namestr(&nmb->question.question_name),
  3417. +       inet_ntoa(ip),rcode));
  3418. +
  3419. +  /* Send a NAME REGISTRATION RESPONSE */
  3420. +  /* a lot of fields get copied from the query. This gives us the IP
  3421. +     and port the reply will be sent to etc */
  3422. +  p2 = *p;
  3423. +  nmb2 = &p2.packet.nmb;
  3424. +
  3425. +  nmb2->header.opcode = 5; 
  3426. +  nmb2->header.response = True;
  3427. +  nmb2->header.nm_flags.bcast = False;
  3428. +  nmb2->header.nm_flags.recursion_available = CanRecurse;
  3429. +  nmb2->header.nm_flags.trunc = False;
  3430. +  nmb2->header.nm_flags.authoritative = True; 
  3431. +  nmb2->header.qdcount = 0;
  3432. +  nmb2->header.ancount = 1;
  3433. +  nmb2->header.nscount = 0;
  3434. +  nmb2->header.arcount = 0;
  3435. +  nmb2->header.rcode = rcode;
  3436. +
  3437. +  nmb2->answers = &answer_rec;
  3438. +  bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
  3439. +  
  3440. +  nmb2->answers->rr_name = nmb->question.question_name;
  3441. +  nmb2->answers->rr_type = nmb->question.question_type;
  3442. +  nmb2->answers->rr_class = nmb->question.question_class;
  3443. +
  3444. +  nmb2->answers->ttl = ttl; 
  3445. +  nmb2->answers->rdlength = 6;
  3446. +  nmb2->answers->rdata[0] = nb_flags;
  3447. +  putip(&nmb2->answers->rdata[2],(char *)&ip);
  3448. +
  3449. +  send_packet(&p2);  
  3450.  }
  3451.  
  3452. +
  3453.  /****************************************************************************
  3454. -a hook for registration of my own names
  3455. +reply to a name status query
  3456.  ****************************************************************************/
  3457. -static void do_registration_hook(void)
  3458. +static void reply_name_status(struct packet_struct *p)
  3459.  {
  3460. -  static int count = 0;
  3461. -  static time_t last_t=0;
  3462. -  time_t t = time(NULL);
  3463. -  
  3464. -  if (last_t && (t-last_t)<REGISTRATION_INTERVAL) return;
  3465. -  last_t = t;
  3466. +  struct nmb_packet *nmb = &p->packet.nmb;
  3467. +  char *qname = nmb->question.question_name.name;
  3468. +  BOOL wildcard = (qname[0] == '*'); 
  3469. +  struct packet_struct p2;
  3470. +  struct nmb_packet *nmb2;
  3471. +  struct res_rec answer_rec;
  3472. +  char *buf;
  3473. +  int count;
  3474. +  int rcode = 0;
  3475. +  struct name_record *n = find_name(&nmb->question.question_name);
  3476. +
  3477. +  DEBUG(3,("Name status for name %s\n",
  3478. +       namestr(&nmb->question.question_name)));
  3479. +
  3480. +  if (!wildcard && (!n || n->source != SELF)) 
  3481. +    return;
  3482. +
  3483. +  /* Send a POSITIVE NAME STATUS RESPONSE */
  3484. +  /* a lot of fields get copied from the query. This gives us the IP
  3485. +     and port the reply will be sent to etc */
  3486. +  p2 = *p;
  3487. +  nmb2 = &p2.packet.nmb;
  3488. +
  3489. +  nmb2->header.response = True;
  3490. +  nmb2->header.nm_flags.bcast = False;
  3491. +  nmb2->header.nm_flags.recursion_available = CanRecurse;
  3492. +  nmb2->header.nm_flags.trunc = False;
  3493. +  nmb2->header.nm_flags.authoritative = True; /* WfWg ignores 
  3494. +                         non-authoritative answers */
  3495. +  nmb2->header.qdcount = 0;
  3496. +  nmb2->header.ancount = 1;
  3497. +  nmb2->header.nscount = 0;
  3498. +  nmb2->header.arcount = 0;
  3499. +  nmb2->header.rcode = rcode;
  3500. +
  3501. +  nmb2->answers = &answer_rec;
  3502. +  bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
  3503. +  
  3504. +
  3505. +  nmb2->answers->rr_name = nmb->question.question_name;
  3506. +  nmb2->answers->rr_type = nmb->question.question_type;
  3507. +  nmb2->answers->rr_class = nmb->question.question_class;
  3508. +  nmb2->answers->ttl = 0; 
  3509. +
  3510. +  for (count=0, n = namelist ; n; n = n->next) {
  3511. +    if (n->source != SELF) continue;
  3512. +    count++;
  3513. +  }
  3514. +
  3515. +  count = MIN(count,400/18); /* XXXX hack, we should calculate exactly
  3516. +                how many will fit */
  3517. +
  3518.    
  3519. -  send_registration(myname,0x20,bcast_ip,myip,count>0,300000);
  3520. -  count++;
  3521. +  buf = &nmb2->answers->rdata[0];
  3522. +  SCVAL(buf,0,count);
  3523. +  buf += 1;
  3524. +
  3525. +  for (n = namelist ; n; n = n->next) 
  3526. +    {
  3527. +      if (n->source != SELF) continue;
  3528. +
  3529. +      bzero(buf,18);
  3530. +      strcpy(buf,n->name.name);
  3531. +      strupper(buf);
  3532. +      buf[15] = n->name.name_type;
  3533. +      buf += 16;
  3534. +      buf[0] = 0x4; /* active */
  3535. +      if (!n->unique) buf[0] |= 0x80; /* group */
  3536. +      buf += 2;
  3537. +      count--;
  3538. +    }
  3539. +
  3540. +  /* XXXXXXX we should fill in more fields of the statistics structure */
  3541. +  bzero(buf,46);
  3542. +  putip(buf,(char *)&myip);
  3543. +  {
  3544. +    extern int num_good_sends,num_good_receives;
  3545. +    SIVAL(buf,20,num_good_sends);
  3546. +    SIVAL(buf,24,num_good_receives);
  3547. +  }
  3548. +
  3549. +  buf += 46;
  3550. +
  3551. +  nmb2->answers->rdlength = PTR_DIFF(buf,&nmb2->answers->rdata[0]);
  3552. +
  3553. +  send_packet(&p2);
  3554.  }
  3555.  
  3556. +
  3557. +
  3558.  /****************************************************************************
  3559. -a hook for browsing handling - called every BROWSE_INTERVAL secs
  3560. +reply to a name query
  3561.  ****************************************************************************/
  3562. -static void do_browse_hook(void)
  3563. +static void reply_name_query(struct packet_struct *p)
  3564.  {
  3565. -  static BOOL first = True;
  3566. -  int i;
  3567. -  static time_t last_t=0;
  3568. -  time_t t = time(NULL);
  3569. -  
  3570. -  if (last_t && (t-last_t)<browse_interval) return;
  3571. -  last_t = t;
  3572. +  struct nmb_packet *nmb = &p->packet.nmb;
  3573. +  char *qname = nmb->question.question_name.name;
  3574. +  BOOL wildcard = (qname[0] == '*'); 
  3575. +  BOOL bcast = nmb->header.nm_flags.bcast;
  3576. +  struct in_addr retip;
  3577. +  int name_type = nmb->question.question_name.name_type;
  3578. +  struct packet_struct p2;
  3579. +  struct nmb_packet *nmb2;
  3580. +  struct res_rec answer_rec;
  3581. +  int ttl=0;
  3582. +  int rcode=0;
  3583. +  BOOL unique = True;
  3584. +
  3585. +  DEBUG(3,("Name query for %s from %s (bcast=%s) - ",
  3586. +       namestr(&nmb->question.question_name),
  3587. +       inet_ntoa(p->ip),
  3588. +       BOOLSTR(bcast)));
  3589.  
  3590. -  for (i=0;i<num_names;i++)
  3591. -    {
  3592. -      BOOL old_found_master = names[i].found_master;
  3593. +  if (wildcard)
  3594. +    retip = myip;
  3595.  
  3596. -      if (!NAMEVALID(i) || !ISGROUP(i)) continue;
  3597. +  if (!wildcard) {
  3598. +    struct name_record *n = find_name(&nmb->question.question_name);
  3599.  
  3600. -      if (names[i].found_master) {
  3601. -    struct in_addr ip2;
  3602. -    announce_host(i,myname,comment);
  3603. -
  3604. -    if (!name_query(names[i].name,0x1d,True,
  3605. -            names[i].master_ip,
  3606. -            &ip2,construct_reply)) {
  3607. -      DEBUG(2,("%s Master browser at %s failed to respond\n",
  3608. -           timestring(),
  3609. -           inet_ntoa(names[i].master_ip)));
  3610. -      names[i].found_master = False;
  3611. -    } else {
  3612. -      names[i].master_ip = ip2;
  3613. -    }
  3614. -      }
  3615. +    if (!n) {
  3616. +      struct in_addr ip;
  3617. +      unsigned long a;
  3618.  
  3619. -      if (!names[i].found_master) {
  3620. -    struct in_addr ip2;
  3621. -    names[i].found_master = find_master(names[i].name,names[i].ip,&ip2,
  3622. -                        construct_reply);
  3623. -
  3624. -    if (names[i].found_master) {
  3625. -      names[i].master_ip = ip2;
  3626. -      DEBUG(1,("%s New master browser for %s at %s\n",
  3627. -           timestring(),
  3628. -           names[i].name,inet_ntoa(names[i].master_ip)));
  3629. -      names[i].count = 0;
  3630. -      announce_host(i,myname,comment);
  3631. -    }
  3632. +      /* only do DNS lookups if the query is for type 0x20 or type 0x0 */
  3633. +      if (name_type != 0x20 && name_type != 0) {
  3634. +    DEBUG(3,("not found\n"));
  3635. +    return;
  3636.        }
  3637.  
  3638. -      if (!names[i].found_master) {
  3639. -    int level = (old_found_master||first)?1:2;
  3640. -    DEBUG(level,("%s Failed to find a master browser for %s using %s\n",
  3641. -             timestring(),
  3642. -             names[i].name,inet_ntoa(names[i].ip)));
  3643. +      /* look it up with DNS */      
  3644. +      a = interpret_addr(qname);
  3645. +
  3646. +      if (!a) {
  3647. +    /* no luck with DNS. We could possibly recurse here XXXX */
  3648. +    /* if this isn't a bcast then we should send a negative reply XXXX */
  3649. +    DEBUG(3,("no recursion\n"));
  3650. +    return;
  3651.        }
  3652. +
  3653. +      /* add it to our cache of names. give it 2 hours in the cache */
  3654. +      putip((char *)&ip,(char *)&a);
  3655. +      n = add_host_entry(qname,name_type,True,2*60*60,DNS,ip);
  3656. +
  3657. +      /* failed to add it? yikes! */
  3658. +      if (!n) return;
  3659. +    }
  3660. +
  3661. +    /* don't respond to bcast queries for group names unless we own them */
  3662. +    if (bcast && !n->unique && !n->source == SELF) {
  3663. +      DEBUG(3,("no bcast replies\n"));
  3664. +      return;
  3665. +    }
  3666. +
  3667. +    /* don't respond to bcast queries for addresses on the same net as the 
  3668. +       machine doing the querying unless its our IP */
  3669. +    if (bcast && 
  3670. +    n->source != SELF && 
  3671. +    same_net(n->ip,p->ip)) {
  3672. +      DEBUG(3,("same net\n"));      
  3673. +      return;
  3674.      }
  3675. -  first = False;
  3676. +
  3677. +    /* is our entry already dead? */
  3678. +    if (n->death_time) {
  3679. +      if (n->death_time < p->timestamp) return;
  3680. +      ttl = n->death_time - p->timestamp;
  3681. +    }
  3682. +
  3683. +    retip = n->ip;
  3684. +    unique = n->unique;
  3685. +  } 
  3686. +
  3687. +  /* if the IP is 0 then substitute my IP - we should see which one is on the 
  3688. +     right interface for the caller to do this right XXX */
  3689. +  if (zero_ip(retip)) retip = myip;
  3690. +  
  3691. +  DEBUG(3,("OK %s rcode=%d\n",inet_ntoa(retip),rcode));      
  3692. +
  3693. +  /* a lot of fields get copied from the query. This gives us the IP
  3694. +     and port the reply will be sent to etc */
  3695. +  p2 = *p;
  3696. +  nmb2 = &p2.packet.nmb;
  3697. +
  3698. +  nmb2->header.response = True;
  3699. +  nmb2->header.nm_flags.bcast = False;
  3700. +  nmb2->header.nm_flags.recursion_available = CanRecurse;
  3701. +  nmb2->header.nm_flags.trunc = False;
  3702. +  nmb2->header.nm_flags.authoritative = True; /* WfWg ignores 
  3703. +                         non-authoritative answers */
  3704. +  nmb2->header.qdcount = 0;
  3705. +  nmb2->header.ancount = 1;
  3706. +  nmb2->header.nscount = 0;
  3707. +  nmb2->header.arcount = 0;
  3708. +  nmb2->header.rcode = rcode;
  3709. +
  3710. +  nmb2->answers = &answer_rec;
  3711. +  bzero((char *)nmb2->answers,sizeof(*nmb2->answers));
  3712. +
  3713. +  nmb2->answers->rr_name = nmb->question.question_name;
  3714. +  nmb2->answers->rr_type = nmb->question.question_type;
  3715. +  nmb2->answers->rr_class = nmb->question.question_class;
  3716. +  nmb2->answers->ttl = ttl;
  3717. +  nmb2->answers->rdlength = 6;
  3718. +  nmb2->answers->rdata[0] = unique?0:0x80; 
  3719. +  nmb2->answers->rdata[1] = 0; 
  3720. +  putip(&nmb2->answers->rdata[2],(char *)&retip);
  3721. +
  3722. +  send_packet(&p2);
  3723. +}
  3724. +
  3725. +
  3726. +
  3727. +/* the global packet linked-list. incoming entries are added to the
  3728. +   end of this list.  it is supposed to remain fairly short so we
  3729. +   won't bother with an end pointer. */
  3730. +static struct packet_struct *packet_queue = NULL;
  3731. +
  3732. +
  3733. +/*******************************************************************
  3734. +  queue a packet into the packet queue
  3735. +  ******************************************************************/
  3736. +static void queue_packet(struct packet_struct *packet)
  3737. +{
  3738. +  struct packet_struct *p;
  3739. +  if (!packet_queue) {
  3740. +    packet->prev = NULL;
  3741. +    packet->next = NULL;
  3742. +    packet_queue = packet;
  3743. +    return;
  3744. +  }
  3745. +  
  3746. +  /* find the bottom */
  3747. +  for (p=packet_queue;p->next;p=p->next) ;
  3748. +
  3749. +  p->next = packet;
  3750. +  packet->next = NULL;
  3751. +  packet->prev = p;
  3752.  }
  3753.  
  3754.  /****************************************************************************
  3755. -  process commands from the client
  3756. -****************************************************************************/
  3757. -void process(void)
  3758. +  process a nmb packet
  3759. +  ****************************************************************************/
  3760. +static void process_nmb(struct packet_struct *p)
  3761.  {
  3762. -  pstring inbuf;
  3763. -  static int trans_num = 0;
  3764. -  int nread;
  3765. +  struct nmb_packet *nmb = &p->packet.nmb;
  3766.  
  3767. -  bzero(inbuf,sizeof(inbuf));
  3768. +  /* if this is a response then ignore it */
  3769. +  if (nmb->header.response) return;
  3770.  
  3771. -  while (True)
  3772. +  switch (nmb->header.opcode) 
  3773.      {
  3774. -      if (!browse)
  3775. +    case 5:
  3776. +    case 8:
  3777. +    case 9:
  3778. +      if (nmb->header.qdcount>0 && 
  3779. +      nmb->header.arcount>0) {
  3780. +    reply_name_reg(p);
  3781. +    return;
  3782. +      }
  3783. +      break;
  3784. +
  3785. +    case 0:
  3786. +      if (nmb->header.qdcount>0) 
  3787.      {
  3788. -      if (!(nread = receive_nmb(inbuf,is_daemon?0:idle_timeout)))
  3789. +      switch (nmb->question.question_type)
  3790.          {
  3791. -          if (is_daemon) continue;
  3792. -          return;
  3793. +        case 0x20:
  3794. +          reply_name_query(p);
  3795. +          break;
  3796. +
  3797. +        case 0x21:
  3798. +          reply_name_status(p);
  3799. +          break;
  3800.          }
  3801. +      return;
  3802.      }
  3803. -      else
  3804. -    {
  3805. -      fd_set fds;
  3806. -      int selrtn;
  3807. -      struct timeval timeout;
  3808. +      break;
  3809.  
  3810. -      do_registration_hook();
  3811. +    case 6:
  3812. +      if (nmb->header.qdcount>0 && 
  3813. +      nmb->header.arcount>0) {
  3814. +    reply_name_release(p);
  3815. +    return;
  3816. +      }
  3817. +      break;
  3818. +    }
  3819.  
  3820. -      do_browse_hook();
  3821. +}
  3822.  
  3823. -      process_138();
  3824.  
  3825. -      FD_ZERO(&fds);
  3826. -      FD_SET(Client,&fds);
  3827.  
  3828. -      timeout.tv_sec = NMBD_SELECT_LOOP;
  3829. -      timeout.tv_usec = 0;
  3830. +/*******************************************************************
  3831. +  run elements off the packet queue till its empty
  3832. +  ******************************************************************/
  3833. +static void run_packet_queue(void)
  3834. +{
  3835. +  struct packet_struct *p;
  3836.  
  3837. -      selrtn = sys_select(&fds,&timeout);
  3838. +  while ((p=packet_queue)) {
  3839. +    switch (p->packet_type)
  3840. +      {
  3841. +      case NMB_PACKET:
  3842. +    process_nmb(p);
  3843. +    break;
  3844.  
  3845. -      if (!FD_ISSET(Client,&fds))
  3846. -        continue;
  3847. +      case DGRAM_PACKET:
  3848. +    process_dgram(p);
  3849. +    break;
  3850. +      }
  3851.  
  3852. -      nread = read_udp_socket(Client, inbuf, sizeof(pstring));
  3853. -      if (nread <= 0)
  3854. -        continue;
  3855. -      num_good_receives++;
  3856. -    }
  3857. +    packet_queue = packet_queue->next;
  3858. +    if (packet_queue) packet_queue->prev = NULL;
  3859. +    free_packet(p);
  3860. +  }
  3861. +}
  3862.  
  3863. -      if (nread < 4)
  3864. -    continue;
  3865.  
  3866. -      if (DEBUGLEVEL > 2)
  3867. -    show_nmb(inbuf);
  3868. +/****************************************************************************
  3869. +  The main select loop, listen for packets and respond
  3870. +  ***************************************************************************/
  3871. +void process(void)
  3872. +{
  3873. +
  3874. +  while (True)
  3875. +    {
  3876. +      fd_set fds;
  3877. +      int selrtn;
  3878. +      struct timeval timeout;
  3879. +
  3880. +      if (needelection && *PrimaryGroup && !RunningElection) {
  3881. +    DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
  3882. +    ElectionCount = 0;
  3883. +    RunningElection = True;
  3884. +    needelection = False;
  3885. +      }
  3886. +
  3887. +      FD_ZERO(&fds);
  3888. +      FD_SET(ClientNMB,&fds);
  3889. +      FD_SET(ClientDGRAM,&fds);
  3890. +      /* during elections we need to send election packets at one
  3891. +         second intervals */
  3892. +      timeout.tv_sec = RunningElection?1:NMBD_SELECT_LOOP;
  3893. +      timeout.tv_usec = 0;
  3894. +
  3895. +      selrtn = sys_select(&fds,&timeout);
  3896. +
  3897. +      if (FD_ISSET(ClientNMB,&fds)) {
  3898. +    struct packet_struct *packet = read_packet(ClientNMB,NMB_PACKET);
  3899. +    if (packet) queue_packet(packet);
  3900. +      }
  3901. +
  3902. +      if (FD_ISSET(ClientDGRAM,&fds)) {
  3903. +    struct packet_struct *packet = read_packet(ClientDGRAM,DGRAM_PACKET);
  3904. +    if (packet) queue_packet(packet);
  3905. +      }
  3906. +
  3907. +      if (RunningElection) 
  3908. +    run_election();
  3909.  
  3910. -      DEBUG(2,("%s Transaction %d\n",timestring(),trans_num));
  3911. +      run_packet_queue();
  3912.  
  3913. -      construct_reply(inbuf);
  3914. +      do_announcements();
  3915.  
  3916. -      trans_num++;
  3917. +      housekeeping();
  3918.      }
  3919.  }
  3920.  
  3921. @@ -1688,27 +1784,59 @@
  3922.      }   
  3923.  
  3924.    if (isdaemon)
  3925. -    Client = open_socket_in(SOCK_DGRAM, port,*lookup?3:0);
  3926. +    ClientNMB = open_socket_in(SOCK_DGRAM, port,0);
  3927.    else
  3928. -    Client = 0;
  3929. +    ClientNMB = 0;
  3930.  
  3931. -  Client138 = open_socket_in(SOCK_DGRAM,138,3);
  3932. +  ClientDGRAM = open_socket_in(SOCK_DGRAM,DGRAM_PORT,3);
  3933.  
  3934. -  if (Client == -1)
  3935. +  if (ClientNMB == -1)
  3936.      return(False);
  3937.  
  3938.    signal(SIGPIPE, SIGNAL_CAST sig_pipe);
  3939.  
  3940. -  set_socket_options(Client,"SO_BROADCAST");
  3941. -  set_socket_options(Client138,"SO_BROADCAST");
  3942. -  set_socket_options(Client,user_socket_options);
  3943. -
  3944. +  set_socket_options(ClientNMB,"SO_BROADCAST");
  3945. +  set_socket_options(ClientDGRAM,"SO_BROADCAST");
  3946.  
  3947.    DEBUG(3, ("Socket opened.\n"));
  3948.    return True;
  3949.  }
  3950.  
  3951.  
  3952. +/*******************************************************************
  3953. +  check that a IP, bcast and netmask and consistent. Must be a 1s
  3954. +  broadcast
  3955. +  ******************************************************************/
  3956. +static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast,
  3957. +              struct in_addr nmask)
  3958. +{
  3959. +  unsigned long a_ip,a_bcast,a_nmask;
  3960. +
  3961. +  a_ip = ntohl(ip.s_addr);
  3962. +  a_bcast = ntohl(bcast.s_addr);
  3963. +  a_nmask = ntohl(nmask.s_addr);
  3964. +
  3965. +  /* check the netmask is sane */
  3966. +  if (((a_nmask>>24)&0xFF) != 0xFF) {
  3967. +    DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
  3968. +    return(False);
  3969. +  }
  3970. +
  3971. +  /* check the IP and bcast are on the same net */
  3972. +  if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
  3973. +    DEBUG(0,("IP and broadcast are on different nets!\n"));
  3974. +    return(False);
  3975. +  }
  3976. +
  3977. +  /* check the IP and bcast are on the same net */
  3978. +  if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
  3979. +    DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
  3980. +    return(False);
  3981. +  }
  3982. +
  3983. +  return(True);
  3984. +}
  3985. +
  3986.  /****************************************************************************
  3987.    initialise connect, service and file structs
  3988.  ****************************************************************************/
  3989. @@ -1737,11 +1865,14 @@
  3990.        Netmask = ip2;   
  3991.        } 
  3992.  
  3993. -    DEBUG(1,("Using IP %s  ",inet_ntoa(myip))); /* core dump reported 
  3994. -                           doing this. Why?? XXXXX  */
  3995. +    DEBUG(1,("Using IP %s  ",inet_ntoa(myip))); 
  3996.      DEBUG(1,("broadcast %s  ",inet_ntoa(bcast_ip)));
  3997.      DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));    
  3998.  
  3999. +    if (!ip_consistent(myip,bcast_ip,Netmask)) {
  4000. +      DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
  4001. +      DEBUG(0,("You are likely to experience problems with this setup!\n"));
  4002. +    }
  4003.    }
  4004.  
  4005.    if (! *myname) {
  4006. @@ -1751,9 +1882,12 @@
  4007.      if (p) *p = 0;
  4008.    }
  4009.  
  4010. -  add_host_name(myname,0x20,&myip);
  4011. -  add_host_name(myname,0x0,&myip);
  4012. -  add_host_name(myname,0x3,&myip);
  4013. +  if (lp_preferred_master()) {
  4014. +    needelection = True;
  4015. +    ElectionCriterion |= (1<<3);
  4016. +  }
  4017. +
  4018. +  ElectionCriterion |= (lp_os_level() << 28);  
  4019.  
  4020.    return True;
  4021.  }
  4022. @@ -1768,21 +1902,14 @@
  4023.    printf("Usage: %s [-n name] [-B bcast address] [-D] [-p port] [-d debuglevel] [-l log basename]\n",pname);
  4024.    printf("Version %s\n",VERSION);
  4025.    printf("\t-D                    become a daemon\n");
  4026. -  printf("\t-P                    passive only. don't respond\n");
  4027. -  printf("\t-R                    only reply to queries, don't actively send claims\n");
  4028.    printf("\t-p port               listen on the specified port\n");
  4029.    printf("\t-d debuglevel         set the debuglevel\n");
  4030.    printf("\t-l log basename.      Basename for log/debug files\n");
  4031.    printf("\t-n netbiosname.       the netbios name to advertise for this host\n");
  4032.    printf("\t-B broadcast address  the address to use for broadcasts\n");
  4033.    printf("\t-N netmask           the netmask to use for subnet determination\n");
  4034. -  printf("\t-L name              lookup this netbios name then exit\n");
  4035. -  printf("\t-S                   serve queries via DNS if not on the same subnet\n");
  4036.    printf("\t-H hosts file        load a netbios hosts file\n");
  4037.    printf("\t-G group name        add a group name to be part of\n");
  4038. -  printf("\t-b                   toggles browsing support (defaults to on)\n");
  4039. -  printf("\t-M group name        searches for a master browser for the given group\n");
  4040. -  printf("\t-T interval          sets the browse announcement interval in seconds\n");
  4041.    printf("\t-C comment           sets the machine comment that appears in browse lists\n");
  4042.    printf("\n");
  4043.  }
  4044. @@ -1790,16 +1917,21 @@
  4045.  
  4046.  /****************************************************************************
  4047.    main program
  4048. -****************************************************************************/
  4049. +  **************************************************************************/
  4050.  int main(int argc,char *argv[])
  4051.  {
  4052. -  int port = 137;
  4053. +  int port = NMB_PORT;
  4054.    int opt;
  4055. -  unsigned int lookup_type = 0;
  4056.    extern FILE *dbf;
  4057.    extern char *optarg;
  4058.  
  4059. -  *lookup = *host_file = 0;
  4060. +  *host_file = 0;
  4061. +
  4062. +#if 0
  4063. +  sleep(10);
  4064. +#endif
  4065. +
  4066. +  StartupTime = time(NULL);
  4067.  
  4068.    TimeInit();
  4069.  
  4070. @@ -1822,65 +1954,39 @@
  4071.  
  4072.    signal(SIGHUP,SIGNAL_CAST sig_hup);
  4073.  
  4074. +  bcast_ip = *interpret_addr2("0.0.0.0");
  4075. +  myip = *interpret_addr2("0.0.0.0");
  4076.  
  4077. -  while ((opt = getopt (argc, argv, "T:O:M:I:C:bAL:i:B:N:Rn:l:d:Dp:hPSH:G:")) != EOF)
  4078. +  while ((opt = getopt (argc, argv, "s:T:I:C:bAi:B:N:Rn:l:d:Dp:hSH:G:")) != EOF)
  4079.      switch (opt)
  4080.        {
  4081. -      case 'T':
  4082. -    browse_interval = atoi(optarg);
  4083. -    browse_interval = MAX(browse_interval,10);
  4084. -    break;
  4085. -      case 'O':
  4086. -    strcpy(user_socket_options,optarg);
  4087. +      case 's':
  4088. +    strcpy(servicesf,optarg);
  4089.      break;
  4090.        case 'C':
  4091. -    strcpy(comment,optarg);
  4092. +    strcpy(ServerComment,optarg);
  4093.      break;
  4094.        case 'G':
  4095. -    add_group_name(optarg);
  4096. -    break;
  4097. -      case 'b':
  4098. -    browse = !browse;
  4099. -    break;
  4100. -      case 'A':
  4101. -    dns_serve = True;
  4102. +    add_domain_entry(optarg,bcast_ip);
  4103.      break;
  4104.        case 'H':
  4105.      strcpy(host_file,optarg);
  4106.      break;
  4107.        case 'I':
  4108. -    {
  4109. -      unsigned long a = interpret_addr(optarg);
  4110. -      putip((char *)&myip,(char *)&a);
  4111. -      got_myip = True;
  4112. -    }
  4113. +    myip = *interpret_addr2(optarg);
  4114. +    got_myip = True;
  4115.      break;
  4116.        case 'B':
  4117. -    {
  4118. -      unsigned long a = interpret_addr(optarg);
  4119. -      putip((char *)&bcast_ip,(char *)&a);
  4120. -      got_bcast = True;
  4121. -    }
  4122. +    bcast_ip = *interpret_addr2(optarg);
  4123. +    got_bcast = True;
  4124.      break;
  4125.        case 'N':
  4126. -    {
  4127. -      unsigned long a = interpret_addr(optarg);
  4128. -      putip((char *)&Netmask,(char *)&a);
  4129. -      got_nmask = True;
  4130. -    }
  4131. +    Netmask = *interpret_addr2(optarg);
  4132. +    got_nmask = True;
  4133.      break;
  4134.        case 'n':
  4135.      strcpy(myname,optarg);
  4136.      break;
  4137. -      case 'P':
  4138. -    {
  4139. -      extern BOOL passive;
  4140. -      passive = True;
  4141. -    }
  4142. -    break;
  4143. -      case 'S':
  4144. -    dns_serve = !dns_serve;
  4145. -    break;
  4146.        case 'l':
  4147.      sprintf(debugf,"%s.nmb",optarg);
  4148.      break;
  4149. @@ -1888,18 +1994,6 @@
  4150.      strcpy(scope,optarg);
  4151.      strupper(scope);
  4152.      break;
  4153. -      case 'L':
  4154. -    strcpy(lookup,optarg);
  4155. -    break;
  4156. -      case 'M':
  4157. -    if (*optarg == '-') {
  4158. -      strcpy(lookup,"\01\02__MSBROWSE__\02");
  4159. -      lookup_type = 1;
  4160. -    } else {
  4161. -      strcpy(lookup,optarg);
  4162. -      lookup_type = 0x1d;
  4163. -    }
  4164. -    break;
  4165.        case 'D':
  4166.      is_daemon = True;
  4167.      break;
  4168. @@ -1914,14 +2008,12 @@
  4169.      exit(0);
  4170.      break;
  4171.        default:
  4172. -    usage(argv[0]);
  4173. -    exit(1);
  4174. +    if (!is_a_socket(0))
  4175. +      usage(argv[0]);
  4176. +    break;
  4177.        }
  4178.  
  4179.    
  4180. -  if (*lookup)
  4181. -    DEBUGLEVEL++;
  4182. -  
  4183.    if (DEBUGLEVEL > 10)
  4184.      {
  4185.        extern FILE *login,*logout;
  4186. @@ -1932,16 +2024,12 @@
  4187.        logout = fopen(fname,"w");
  4188.      }
  4189.    
  4190. -  if (*lookup)
  4191. -    {
  4192. -      if (dbf)
  4193. -    fclose(dbf);
  4194. -      dbf = stdout;
  4195. -    }
  4196. -
  4197.    DEBUG(1,("%s netbios nameserver version %s started\n",timestring(),VERSION));
  4198.    DEBUG(1,("Copyright Andrew Tridgell 1994\n"));
  4199.  
  4200. +  if (!reload_services(False))
  4201. +    return(-1);    
  4202. +
  4203.    if (*host_file)
  4204.      {
  4205.        load_hosts_file(host_file);
  4206. @@ -1950,34 +2038,12 @@
  4207.  
  4208.    init_structs();
  4209.  
  4210. -  if (*lookup) {
  4211. -    BOOL bcast = True;
  4212. -    int retries = 2;
  4213. -    char *p = strchr(lookup,'#');
  4214. -    struct in_addr ip;
  4215. -    if (p) {
  4216. -      *p = 0;
  4217. -      sscanf(p+1,"%x",&lookup_type);
  4218. -      bcast = False;
  4219. -      retries = 1;
  4220. -    }
  4221. -    if (!open_sockets(True,port)) return(1);
  4222. -    while (retries--)
  4223. -      if (name_query(lookup,lookup_type,bcast,bcast_ip,&ip,NULL)) {
  4224. -    printf("%s %s\n",inet_ntoa(ip),lookup);
  4225. -    name_status(lookup,lookup_type,ip,NULL,NULL);
  4226. -    return(0);
  4227. -      } 
  4228. -    printf("couldn't find name %s\n",lookup);
  4229. -    return(0);
  4230. -  }
  4231. -
  4232. -  if (!*comment)
  4233. -    strcpy(comment,"Samba %v");
  4234. -  string_sub(comment,"%v",VERSION);
  4235. -  string_sub(comment,"%h",myhostname);
  4236. +  if (!*ServerComment)
  4237. +    strcpy(ServerComment,"Samba %v");
  4238. +  string_sub(ServerComment,"%v",VERSION);
  4239. +  string_sub(ServerComment,"%h",myhostname);
  4240.  
  4241. -  check_names();
  4242. +  add_my_names();
  4243.  
  4244.    DEBUG(3,("Checked names\n"));
  4245.    
  4246. @@ -1990,6 +2056,7 @@
  4247.      is_daemon = True;
  4248.    }
  4249.    
  4250. +
  4251.    if (is_daemon) {
  4252.      DEBUG(2,("%s becoming a daemon\n",timestring()));
  4253.      become_daemon();
  4254. diff -u -r --new-file last-version/source/nameserv2.c samba-1.9.15/source/nameserv2.c
  4255. --- last-version/source/nameserv2.c    Sun Nov 12 21:35:59 1995
  4256. +++ samba-1.9.15/source/nameserv2.c    Tue Nov 14 21:40:10 1995
  4257. @@ -82,19 +82,26 @@
  4258.  /* here are my election parameters */
  4259.  
  4260.  /* NTAS uses 2, NT uses 1, WfWg uses 0 */
  4261. -#define OS_LEVEL 3
  4262. -#define PREFERRED_MASTER 1
  4263.  #define MAINTAIN_LIST 1
  4264.  #define ELECTION_VERSION 1
  4265.  
  4266.  static BOOL RunningElection = False;
  4267. -static BOOL needelection = True;
  4268. +static BOOL needelection = False;
  4269.  static int ElectionCount = 0;
  4270.  static int StartupTime =0;
  4271. -static uint32 ElectionCriterion = 
  4272. -(OS_LEVEL<<28)|(PREFERRED_MASTER<<3)|(MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
  4273. +
  4274. +
  4275. +/* WfWg uses 01040b01 */
  4276. +/* Win95 uses 01041501 */
  4277. +/* NTAS uses ?? */
  4278. +static uint32 ElectionCriterion = (MAINTAIN_LIST<<1)|(ELECTION_VERSION<<8);
  4279. +
  4280. +/* we currently support being the master for just one group. Being the
  4281. +   master for more than one group might be tricky as NetServerEnum is
  4282. +   often asked for a list without naming the group */
  4283.  static fstring PrimaryGroup="";
  4284.  
  4285. +#define AM_MASTER (PrimaryGroup[0] && (ServerType & SV_TYPE_MASTER_BROWSER))
  4286.  
  4287.  #define MSBROWSE "\001\002__MSBROWSE__\002"
  4288.  
  4289. @@ -107,8 +114,7 @@
  4290.  
  4291.    DEBUG(0,("Got SIGHUP (reload not implemented)\n"));
  4292.    dump_names();
  4293. -  if (!is_daemon)
  4294. -    exit(1);
  4295. +  reload_services(True);
  4296.  
  4297.    BlockSignals(False);
  4298.  #ifndef DONT_REINSTALL_SIG
  4299. @@ -334,7 +340,7 @@
  4300.      n = n2;
  4301.    }
  4302.  
  4303. -  if (ttl) n->death_time = time(NULL)+ttl;
  4304. +  if (ttl) n->death_time = time(NULL)+ttl*3;
  4305.    n->ip = ip;
  4306.    n->unique = unique;
  4307.    n->source = source;
  4308. @@ -407,7 +413,7 @@
  4309.    StrnCpy(s->name,name,sizeof(s->name)-1);
  4310.    StrnCpy(s->comment,comment,sizeof(s->comment)-1);
  4311.    s->servertype = servertype;
  4312. -  s->death_time = ttl?time(NULL)+ttl:0;    
  4313. +  s->death_time = ttl?time(NULL)+ttl*3:0;
  4314.    strupper(s->name);
  4315.    if (s->servertype & SV_TYPE_DOMAIN_ENUM) strupper(s->comment);
  4316.  
  4317. @@ -433,6 +439,7 @@
  4318.    add_host_entry("__SAMBA__",0x0,True,0,SELF,ip);
  4319.    add_host_entry(myname,0x20,True,0,SELF,ip);
  4320.    add_host_entry(myname,0x0,True,0,SELF,ip);
  4321. +  add_host_entry(myname,0x1f,True,0,SELF,ip); /* used for chat, I think */
  4322.    if (!domainlist)
  4323.      add_domain_entry(lp_workgroup(),bcast_ip);
  4324.    add_server_entry(myname,
  4325. @@ -442,9 +449,48 @@
  4326.  
  4327.  
  4328.  /*******************************************************************
  4329. -  delete old names from the namelist
  4330. +  write out browse.dat
  4331.    ******************************************************************/
  4332. -static void housekeeping(void)
  4333. +static void write_browse_list(void)
  4334. +{
  4335. +  struct server_record *s;
  4336. +  pstring fname,fnamenew;
  4337. +  FILE *f;
  4338. +  
  4339. +  updatecount++;
  4340. +
  4341. +  strcpy(fname,lp_lockdir());
  4342. +  trim_string(fname,NULL,"/");
  4343. +  strcat(fname,"/");
  4344. +  strcat(fname,SERVER_LIST);
  4345. +  strcpy(fnamenew,fname);
  4346. +  strcat(fnamenew,".");
  4347. +  
  4348. +  f = fopen(fnamenew,"w");
  4349. +  
  4350. +  if (!f) {
  4351. +    DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
  4352. +    return;
  4353. +  }
  4354. +  
  4355. +  for (s=serverlist; s ; s = s->next) {
  4356. +    /* don't list domains I don't have a master for */
  4357. +    if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
  4358. +    
  4359. +    fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
  4360. +  }
  4361. +  
  4362. +  
  4363. +  fclose(f);
  4364. +  unlink(fname);
  4365. +  rename(fnamenew,fname);   
  4366. +  DEBUG(3,("Wrote browse list %s\n",fname));
  4367. +}
  4368. +
  4369. +/*******************************************************************
  4370. +  expire old names in the namelist and serverlist
  4371. +  ******************************************************************/
  4372. +static void expire_names(void)
  4373.  {
  4374.    static time_t lastrun=0;
  4375.    time_t t = time(NULL);
  4376. @@ -453,7 +499,6 @@
  4377.    struct server_record *s;
  4378.    struct server_record *nexts;
  4379.  
  4380. -  /* don't run this to often */
  4381.    if (!lastrun) lastrun = t;
  4382.    if (t < lastrun + 5) return;
  4383.    lastrun = t;
  4384. @@ -477,6 +522,7 @@
  4385.    for (s = serverlist; s; s = nexts) {
  4386.      if (s->death_time && s->death_time < t) {
  4387.        DEBUG(3,("Removing dead server %s\n",s->name));
  4388. +      updatedlists = True;
  4389.        nexts = s->next;
  4390.        if (s->prev) s->prev->next = s->next;
  4391.        if (s->next) s->next->prev = s->prev;
  4392. @@ -486,44 +532,38 @@
  4393.        nexts = s->next;
  4394.      }
  4395.    }
  4396. -
  4397. -
  4398. -  /* write out the browse.dat database for smbd to get */
  4399. -  if (!updatedlists) return;
  4400. -  updatedlists = False;
  4401. -  updatecount++;
  4402. -  {
  4403. -    pstring fname,fnamenew;
  4404. -    FILE *f;
  4405. +}
  4406.  
  4407. -    strcpy(fname,lp_lockdir());
  4408. -    trim_string(fname,NULL,"/");
  4409. -    strcat(fname,"/");
  4410. -    strcat(fname,SERVER_LIST);
  4411. -    strcpy(fnamenew,fname);
  4412. -    strcat(fnamenew,".");
  4413.  
  4414. -    f = fopen(fnamenew,"w");
  4415. +/*******************************************************************
  4416. +  delete old names from the namelist
  4417. +  ******************************************************************/
  4418. +static void housekeeping(void)
  4419. +{
  4420. +  time_t t = time(NULL);
  4421.  
  4422. -    if (!f) {
  4423. -      DEBUG(4,("Can't open %s - %s\n",fnamenew,strerror(errno)));
  4424. -      return;
  4425. -    }
  4426. +  expire_names();
  4427.  
  4428. -    for (s=serverlist; s ; s = s->next) {
  4429. -      /* don't list domains I don't have a master for */
  4430. -      if ((s->servertype & SV_TYPE_DOMAIN_ENUM) && !s->comment[0]) continue;
  4431. +  /* write out the browse.dat database for smbd to get */
  4432. +  if (updatedlists) {
  4433. +    write_browse_list();
  4434. +    updatedlists = False;
  4435. +  }
  4436.  
  4437. -      fprintf(f,"\"%s\"\t%08x\t\"%s\"\n",s->name,s->servertype,s->comment);
  4438. +  {
  4439. +    /* occasionally check to see if the master browser is around */
  4440. +    static time_t lastrun=0;
  4441. +    if (!lastrun) lastrun = t;
  4442. +    if (t < lastrun + 5*60) return;
  4443. +    lastrun = t;
  4444. +
  4445. +    if (!AM_MASTER && *PrimaryGroup &&
  4446. +    !name_query(ClientNMB,PrimaryGroup,0x1d,True,False,
  4447. +            bcast_ip,NULL,queue_packet)) {
  4448. +      DEBUG(2,("Forcing election on %s\n",PrimaryGroup));
  4449. +      needelection = True;
  4450.      }
  4451. -
  4452. -
  4453. -    fclose(f);
  4454. -    unlink(fname);
  4455. -    rename(fnamenew,fname);   
  4456. -    DEBUG(3,("Wrote browse list %s\n",fname));
  4457.    }
  4458. -
  4459.  }
  4460.  
  4461.  
  4462. @@ -630,11 +670,11 @@
  4463.    ******************************************************************/
  4464.  static BOOL same_net(struct in_addr ip1,struct in_addr ip2)
  4465.  {
  4466. -  unsigned int net1,net2,nmask;
  4467. +  unsigned long net1,net2,nmask;
  4468.  
  4469. -  putip((char *)&nmask,(char *)&Netmask);
  4470. -  putip((char *)&net1,(char *)&ip1);
  4471. -  putip((char *)&net2,(char *)&ip2);
  4472. +  nmask = ntohl(Netmask.s_addr);
  4473. +  net1 = ntohl(ip1.s_addr);
  4474. +  net2 = ntohl(ip2.s_addr);
  4475.          
  4476.    return((net1 & nmask) == (net2 & nmask));
  4477.  }
  4478. @@ -779,11 +819,14 @@
  4479.    pstring outbuf;
  4480.    char *p;
  4481.    char *namep;
  4482. +  char *stypep;
  4483.    char *commentp;
  4484.  
  4485.    if (needannounce) {
  4486. -    d->announce_interval = 0;
  4487. -    d->lastannounce_time = t - 1;
  4488. +    /* drop back to a max 3 minute announce - this is to prevent a
  4489. +       single lost packet from stuffing things up for too long */
  4490. +    d->announce_interval = MIN(d->announce_interval,3*60);
  4491. +    d->lastannounce_time = t - (d->announce_interval+1);
  4492.    }
  4493.  
  4494.    /* announce every minute at first then progress to every 12 mins */
  4495. @@ -813,6 +856,7 @@
  4496.    strupper(p+5);
  4497.    CVAL(p,21) = 2; /* major version */
  4498.    CVAL(p,22) = 0; /* minor version */
  4499. +  stypep = p+23;
  4500.    SIVAL(p,23,ServerType);
  4501.    SSVAL(p,27,0xaa55); /* browse signature */
  4502.    SSVAL(p,29,1); /* browse version */
  4503. @@ -824,8 +868,10 @@
  4504.    send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  4505.           my_name,d->name,0,0x1d,d->bcast_ip,myip);
  4506.  
  4507. -  if ((ServerType & SV_TYPE_MASTER_BROWSER) &&
  4508. -      *PrimaryGroup &&
  4509. +  /* if I'm the master then I also need to do a local master and
  4510. +     domain announcement */
  4511. +
  4512. +  if (AM_MASTER &&
  4513.        strequal(d->name,PrimaryGroup) &&
  4514.        ip_equal(bcast_ip,d->bcast_ip)) {
  4515.  
  4516. @@ -840,6 +886,7 @@
  4517.      strupper(namep);
  4518.      StrnCpy(commentp,myname,15);
  4519.      strupper(commentp);
  4520. +    SIVAL(stypep,0,(unsigned)0x80000000);
  4521.      p = commentp + strlen(commentp) + 1;
  4522.  
  4523.      send_udp_dgram(ClientDGRAM,outbuf,PTR_DIFF(p,outbuf),
  4524. @@ -875,10 +922,39 @@
  4525.  }
  4526.  
  4527.  
  4528. +/*******************************************************************
  4529. +  am I listening on a name. Should check name_type as well 
  4530. +
  4531. +  This is primarily used to prevent us gathering server lists from
  4532. +  other workgroups we aren't a part of
  4533. +  ******************************************************************/
  4534. +static BOOL listening(struct nmb_name *n)
  4535. +{
  4536. +  if (!strequal(n->scope,scope)) return(False);
  4537. +
  4538. +  if (strequal(n->name,myname) ||
  4539. +      strequal(n->name,PrimaryGroup) ||
  4540. +      strequal(n->name,MSBROWSE))
  4541. +    return(True);
  4542. +
  4543. +  return(False);
  4544. +}
  4545.  
  4546.  
  4547.  /*******************************************************************
  4548.    process a domain announcement frame
  4549. +
  4550. +  Announce frames come in 3 types. Servers send host announcements
  4551. +  (command=1) to let the master browswer know they are
  4552. +  available. Master browsers send local master announcements
  4553. +  (command=15) to let other masters and backups that they are the
  4554. +  master. They also send domain announcements (command=12) to register
  4555. +  the domain
  4556. +
  4557. +  The comment field of domain announcements contains the master
  4558. +  browser name. The servertype is used by NetServerEnum to select
  4559. +  resources. We just have to pass it to smbd (via browser.dat) and let
  4560. +  the client choose using bit masks.
  4561.    ******************************************************************/
  4562.  static void process_announce(struct packet_struct *p,int command,char *buf)
  4563.  {
  4564. @@ -900,12 +976,24 @@
  4565.  
  4566.    if (strequal(dgram->source_name.name,myname)) return;
  4567.  
  4568. +  if (!listening(&dgram->dest_name)) return;
  4569. +
  4570. +  /* add them to our browse list */
  4571.    add_server_entry(name,servertype,ttl,comment);
  4572.  }
  4573.  
  4574.  
  4575.  /*******************************************************************
  4576.    process a backup list request
  4577. +
  4578. +  A client send a backup list request to ask for a list of servers on
  4579. +  the net that maintain server lists for a domain. A server is then
  4580. +  chosen from this list to send NetServerEnum commands to to list
  4581. +  available servers.
  4582. +
  4583. +  Currently samba only sends back one name in the backup list, its
  4584. +  wn. For larger nets we'll have to add backups and send "become
  4585. +  backup" requests occasionally.
  4586.    ******************************************************************/
  4587.  static void process_backup_list(struct packet_struct *p,char *buf)
  4588.  {
  4589. @@ -921,10 +1009,12 @@
  4590.  
  4591.    if (count <= 0) return;
  4592.  
  4593. -  if (!*PrimaryGroup || !(ServerType & SV_TYPE_MASTER_BROWSER) ||
  4594. +  if (!AM_MASTER || 
  4595.        !strequal(PrimaryGroup,dgram->dest_name.name))
  4596.      return;
  4597.  
  4598. +  if (!listening(&dgram->dest_name)) return;
  4599. +
  4600.    send_backup_list(myname,token,
  4601.             &dgram->source_name,
  4602.             p->ip);
  4603. @@ -957,6 +1047,8 @@
  4604.  
  4605.  /*******************************************************************
  4606.    process a election packet
  4607. +
  4608. +  An election dynamically decides who will be the master. 
  4609.    ******************************************************************/
  4610.  static void process_election(struct packet_struct *p,char *buf)
  4611.  {
  4612. @@ -972,29 +1064,33 @@
  4613.         name,version,criterion,timeup));
  4614.  
  4615.    if (strequal(dgram->source_name.name,myname)) return;
  4616. -  if (!*PrimaryGroup ||
  4617. -      !strequal(dgram->dest_name.name,PrimaryGroup)) return;
  4618. +
  4619. +  if (!listening(&dgram->dest_name)) return;
  4620.  
  4621.    if (win_election(version,criterion,timeup,name)) {
  4622.      if (!RunningElection) {
  4623. -      DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
  4624.        needelection = True;
  4625.        ElectionCount=0;
  4626.      }
  4627.    } else {
  4628. -    RunningElection = False;
  4629.      needelection = False;
  4630. -    /* if we are the master then remove our masterly name */
  4631. -    if (ServerType & SV_TYPE_MASTER_BROWSER) {
  4632. +    if (RunningElection) {
  4633. +      RunningElection = False;
  4634.        DEBUG(3,(">>> Lost election on %s <<<\n",PrimaryGroup));
  4635. -      become_nonmaster();
  4636. +
  4637. +      /* if we are the master then remove our masterly names */
  4638. +      if (AM_MASTER)
  4639. +    become_nonmaster();
  4640.      }
  4641.    }
  4642. -
  4643.  }
  4644.  
  4645. +
  4646.  /*******************************************************************
  4647.    process a announcement request
  4648. +
  4649. +  clients send these when they want everyone to send an announcement
  4650. +  immediately. This can cause quite a storm of packets!
  4651.    ******************************************************************/
  4652.  static void process_announce_request(struct packet_struct *p,char *buf)
  4653.  {
  4654. @@ -1174,7 +1270,6 @@
  4655.    DEBUG(3,("Name release on name %s rcode=%d\n",
  4656.         namestr(&nmb->question.question_name),rcode));
  4657.  
  4658. -
  4659.    if (bcast) return;
  4660.  
  4661.    /* Send a NAME RELEASE RESPONSE */
  4662. @@ -1246,14 +1341,14 @@
  4663.        rcode = 6;
  4664.      } else {
  4665.        n->ip = ip;
  4666. -      n->death_time = ttl?p->timestamp+ttl:0;
  4667. +      n->death_time = ttl?p->timestamp+ttl*3:0;
  4668.        DEBUG(3,("%s changed owner to %s\n",
  4669.             namestr(&n->name),inet_ntoa(n->ip)));
  4670.      }
  4671.        } else {
  4672.      /* refresh the name */
  4673.      if (n->source != SELF)
  4674. -      n->death_time = ttl?p->timestamp + ttl:0;
  4675. +      n->death_time = ttl?p->timestamp + ttl*3:0;
  4676.        }
  4677.      } else {
  4678.        /* add the name to our database */
  4679. @@ -1351,7 +1446,7 @@
  4680.    nmb2->answers->ttl = 0; 
  4681.  
  4682.    for (count=0, n = namelist ; n; n = n->next) {
  4683. -    if (n->source != SELF && n->source != LMHOSTS) continue;
  4684. +    if (n->source != SELF) continue;
  4685.      count++;
  4686.    }
  4687.  
  4688. @@ -1365,7 +1460,7 @@
  4689.  
  4690.    for (n = namelist ; n; n = n->next) 
  4691.      {
  4692. -      if (n->source != SELF && n->source != LMHOSTS) continue;
  4693. +      if (n->source != SELF) continue;
  4694.  
  4695.        bzero(buf,18);
  4696.        strcpy(buf,n->name.name);
  4697. @@ -1459,10 +1554,10 @@
  4698.        return;
  4699.      }
  4700.  
  4701. -    /* don't respond to bcast queries for addresses on the same net as the machine 
  4702. -       doing the querying unless its our IP (or something from LMHOSTS) */
  4703. +    /* don't respond to bcast queries for addresses on the same net as the 
  4704. +       machine doing the querying unless its our IP */
  4705.      if (bcast && 
  4706. -    n->source != SELF && n->source != LMHOSTS && 
  4707. +    n->source != SELF && 
  4708.      same_net(n->ip,p->ip)) {
  4709.        DEBUG(3,("same net\n"));      
  4710.        return;
  4711. @@ -1479,7 +1574,7 @@
  4712.    } 
  4713.  
  4714.    /* if the IP is 0 then substitute my IP - we should see which one is on the 
  4715. -     right interface for the caller to do this right */
  4716. +     right interface for the caller to do this right XXX */
  4717.    if (zero_ip(retip)) retip = myip;
  4718.    
  4719.    DEBUG(3,("OK %s rcode=%d\n",inet_ntoa(retip),rcode));      
  4720. @@ -1636,6 +1731,7 @@
  4721.        struct timeval timeout;
  4722.  
  4723.        if (needelection && *PrimaryGroup && !RunningElection) {
  4724. +    DEBUG(3,(">>> Starting election on %s <<<\n",PrimaryGroup));
  4725.      ElectionCount = 0;
  4726.      RunningElection = True;
  4727.      needelection = False;
  4728. @@ -1644,6 +1740,8 @@
  4729.        FD_ZERO(&fds);
  4730.        FD_SET(ClientNMB,&fds);
  4731.        FD_SET(ClientDGRAM,&fds);
  4732. +      /* during elections we need to send election packets at one
  4733. +         second intervals */
  4734.        timeout.tv_sec = RunningElection?1:NMBD_SELECT_LOOP;
  4735.        timeout.tv_usec = 0;
  4736.  
  4737. @@ -1705,6 +1803,40 @@
  4738.  }
  4739.  
  4740.  
  4741. +/*******************************************************************
  4742. +  check that a IP, bcast and netmask and consistent. Must be a 1s
  4743. +  broadcast
  4744. +  ******************************************************************/
  4745. +static BOOL ip_consistent(struct in_addr ip,struct in_addr bcast,
  4746. +              struct in_addr nmask)
  4747. +{
  4748. +  unsigned long a_ip,a_bcast,a_nmask;
  4749. +
  4750. +  a_ip = ntohl(ip.s_addr);
  4751. +  a_bcast = ntohl(bcast.s_addr);
  4752. +  a_nmask = ntohl(nmask.s_addr);
  4753. +
  4754. +  /* check the netmask is sane */
  4755. +  if (((a_nmask>>24)&0xFF) != 0xFF) {
  4756. +    DEBUG(0,("Insane netmask %s\n",inet_ntoa(nmask)));
  4757. +    return(False);
  4758. +  }
  4759. +
  4760. +  /* check the IP and bcast are on the same net */
  4761. +  if ((a_ip&a_nmask) != (a_bcast&a_nmask)) {
  4762. +    DEBUG(0,("IP and broadcast are on different nets!\n"));
  4763. +    return(False);
  4764. +  }
  4765. +
  4766. +  /* check the IP and bcast are on the same net */
  4767. +  if ((a_bcast|a_nmask) != 0xFFFFFFFF) {
  4768. +    DEBUG(0,("Not a ones based broadcast %s\n",inet_ntoa(bcast)));
  4769. +    return(False);
  4770. +  }
  4771. +
  4772. +  return(True);
  4773. +}
  4774. +
  4775.  /****************************************************************************
  4776.    initialise connect, service and file structs
  4777.  ****************************************************************************/
  4778. @@ -1733,11 +1865,14 @@
  4779.        Netmask = ip2;   
  4780.        } 
  4781.  
  4782. -    DEBUG(1,("Using IP %s  ",inet_ntoa(myip))); /* core dump reported 
  4783. -                           doing this. Why?? XXXXX  */
  4784. +    DEBUG(1,("Using IP %s  ",inet_ntoa(myip))); 
  4785.      DEBUG(1,("broadcast %s  ",inet_ntoa(bcast_ip)));
  4786.      DEBUG(1,("netmask %s\n",inet_ntoa(Netmask)));    
  4787.  
  4788. +    if (!ip_consistent(myip,bcast_ip,Netmask)) {
  4789. +      DEBUG(0,("WARNING: The IP address, broadcast and Netmask are not consistent\n"));
  4790. +      DEBUG(0,("You are likely to experience problems with this setup!\n"));
  4791. +    }
  4792.    }
  4793.  
  4794.    if (! *myname) {
  4795. @@ -1747,6 +1882,13 @@
  4796.      if (p) *p = 0;
  4797.    }
  4798.  
  4799. +  if (lp_preferred_master()) {
  4800. +    needelection = True;
  4801. +    ElectionCriterion |= (1<<3);
  4802. +  }
  4803. +
  4804. +  ElectionCriterion |= (lp_os_level() << 28);  
  4805. +
  4806.    return True;
  4807.  }
  4808.  
  4809. @@ -1866,8 +2008,9 @@
  4810.      exit(0);
  4811.      break;
  4812.        default:
  4813. -    usage(argv[0]);
  4814. -    exit(1);
  4815. +    if (!is_a_socket(0))
  4816. +      usage(argv[0]);
  4817. +    break;
  4818.        }
  4819.  
  4820.    
  4821. diff -u -r --new-file last-version/source/nmblib.c samba-1.9.15/source/nmblib.c
  4822. --- last-version/source/nmblib.c    Sun Nov 12 15:16:26 1995
  4823. +++ samba-1.9.15/source/nmblib.c    Tue Nov 14 21:23:08 1995
  4824. @@ -1,7 +1,7 @@
  4825.  /* 
  4826.     Unix SMB/Netbios implementation.
  4827.     Version 1.9.
  4828. -   NBT netbios routines and daemon - version 2
  4829. +   NBT netbios library routines
  4830.     Copyright (C) Andrew Tridgell 1994-1995
  4831.     
  4832.     This program is free software; you can redistribute it and/or modify
  4833. @@ -649,7 +649,9 @@
  4834.  
  4835.  
  4836.  /****************************************************************************
  4837. -  do a netbios name status to a host
  4838. +  do a netbios name status query on a host
  4839. +
  4840. +  the "master" parameter is a hack used for finding workgroups.
  4841.    **************************************************************************/
  4842.  BOOL name_status(int fd,char *name,int name_type,BOOL recurse,
  4843.              struct in_addr to_ip,char *master,void (*fn)())
  4844. @@ -818,7 +820,8 @@
  4845.        struct nmb_packet *nmb2 = &p2->packet.nmb;
  4846.        if (nmb->header.name_trn_id != nmb2->header.name_trn_id ||
  4847.            !nmb2->header.response) {
  4848. -        /* its not for us - maybe deal with it later (put it on the queue?) */
  4849. +        /* its not for us - maybe deal with it later 
  4850. +           (put it on the queue?) */
  4851.          if (fn) 
  4852.            fn(p2);
  4853.          else
  4854. @@ -836,12 +839,15 @@
  4855.          continue;
  4856.        }
  4857.  
  4858. -      putip((char *)ip,&nmb2->answers->rdata[2]);
  4859. -      DEBUG(2,("Got a positive name query response from %s",
  4860. -           inet_ntoa(p2->ip)));
  4861. -      DEBUG(2,(" (%s)\n",inet_ntoa(*ip)));
  4862. +      if (ip) {
  4863. +        putip((char *)ip,&nmb2->answers->rdata[2]);
  4864. +        DEBUG(fn?3:2,("Got a positive name query response from %s",
  4865. +              inet_ntoa(p2->ip)));
  4866. +        DEBUG(fn?3:2,(" (%s)\n",inet_ntoa(*ip)));
  4867. +      }
  4868.        found=True; retries=0;
  4869.        free_packet(p2);
  4870. +      if (fn) break;
  4871.      }
  4872.      }
  4873.  
  4874. @@ -851,6 +857,9 @@
  4875.  
  4876.  /****************************************************************************
  4877.    construct and send a netbios DGRAM
  4878. +
  4879. +  Note that this currently sends all answers to port 138. thats the
  4880. +  wrong things to do! I should send to the requestors port. XXX
  4881.    **************************************************************************/
  4882.  BOOL send_udp_dgram(int fd,char *buf,int len,
  4883.                 char *srcname,char *dstname,
  4884. diff -u -r --new-file last-version/source/reply.c samba-1.9.15/source/reply.c
  4885. --- last-version/source/reply.c    Mon Nov  6 16:14:59 1995
  4886. +++ samba-1.9.15/source/reply.c    Mon Nov 13 19:30:23 1995
  4887. @@ -707,22 +707,15 @@
  4888.  
  4889.    /* turn strings of spaces into a . */  
  4890.    {
  4891. -    p = strrchr(mask,' ');
  4892. -    if (p)
  4893. +    trim_string(mask,NULL," ");
  4894. +    if ((p = strrchr(mask,' ')))
  4895.        {
  4896. -    if (!p[1])
  4897. -      {
  4898. -        while (*p == ' ') {*p = 0;p--;}
  4899. -      }
  4900. -    else
  4901. -      {
  4902. -        fstring ext;
  4903. -        strcpy(ext,p+1);
  4904. -        *p = 0;
  4905. -        trim_string(mask,NULL," ");
  4906. -        strcat(mask,".");
  4907. -        strcat(mask,ext);
  4908. -      }
  4909. +    fstring ext;
  4910. +    strcpy(ext,p+1);
  4911. +    *p = 0;
  4912. +    trim_string(mask,NULL," ");
  4913. +    strcat(mask,".");
  4914. +    strcat(mask,ext);
  4915.        }
  4916.    }
  4917.  
  4918. diff -u -r --new-file last-version/source/server.c samba-1.9.15/source/server.c
  4919. --- last-version/source/server.c    Sun Nov 12 13:21:30 1995
  4920. +++ samba-1.9.15/source/server.c    Tue Nov 14 23:15:32 1995
  4921. @@ -185,6 +185,11 @@
  4922.    if (S_ISDIR(sbuf->st_mode))
  4923.      result = aDIR | (result & aRONLY);
  4924.  
  4925. +#if LINKS_READ_ONLY
  4926. +  if (S_ISLNK(sbuf->st_mode) && S_ISDIR(sbuf->st_mode))
  4927. +    result |= aRONLY;
  4928. +#endif
  4929. +
  4930.    /* hide files with a name starting with a . */
  4931.    if (lp_hide_dot_files(SNUM(cnum)))
  4932.      {
  4933. @@ -2725,7 +2730,6 @@
  4934.  int reply_lanman1(char *outbuf)
  4935.  {
  4936.    int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  4937. -  int outsize;
  4938.    int secword=0;
  4939.    BOOL doencrypt = SMBENCRYPT();
  4940.    time_t t = time(NULL);
  4941. @@ -2733,13 +2737,20 @@
  4942.    if (lp_security()>=SEC_USER) secword |= 1;
  4943.    if (doencrypt) secword |= 2;
  4944.  
  4945. -  outsize = set_message(outbuf,13,doencrypt?8:0,True);
  4946. +  set_message(outbuf,13,doencrypt?8:0,True);
  4947.    SSVAL(outbuf,smb_vwv1,secword); 
  4948.  #ifdef SMB_PASSWD
  4949.    /* Create a token value and add it to the outgoing packet. */
  4950.    if (doencrypt) 
  4951.      generate_next_challenge(smb_buf(outbuf));
  4952.  #endif
  4953. +
  4954. +  Protocol = PROTOCOL_LANMAN1;
  4955. +
  4956. +  if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
  4957. +    DEBUG(3,("using password server validation\n"));
  4958. +  }
  4959. +
  4960.    CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
  4961.    SSVAL(outbuf,smb_vwv2,maxxmit);
  4962.    SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
  4963. @@ -2751,9 +2762,7 @@
  4964.  
  4965.    put_dos_date(outbuf,smb_vwv8,t);
  4966.  
  4967. -  Protocol = PROTOCOL_LANMAN1;
  4968. -
  4969. -  return outsize;
  4970. +  return (smb_len(outbuf)+4);
  4971.  }
  4972.  
  4973.  
  4974. @@ -2763,7 +2772,6 @@
  4975.  int reply_lanman2(char *outbuf)
  4976.  {
  4977.    int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
  4978. -  int outsize;
  4979.    int secword=0;
  4980.    BOOL doencrypt = SMBENCRYPT();
  4981.    time_t t = time(NULL);
  4982. @@ -2771,7 +2779,7 @@
  4983.    if (lp_security()>=SEC_USER) secword |= 1;
  4984.    if (doencrypt) secword |= 2;
  4985.  
  4986. -  outsize = set_message(outbuf,13,doencrypt?8:0,True);
  4987. +  set_message(outbuf,13,doencrypt?8:0,True);
  4988.    SSVAL(outbuf,smb_vwv1,secword); 
  4989.  #ifdef SMB_PASSWD
  4990.    /* Create a token value and add it to the outgoing packet. */
  4991. @@ -2795,7 +2803,7 @@
  4992.    SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
  4993.    put_dos_date(outbuf,smb_vwv8,t);
  4994.  
  4995. -  return (outsize);
  4996. +  return (smb_len(outbuf)+4);
  4997.  }
  4998.  
  4999.  /****************************************************************************
  5000. diff -u -r --new-file last-version/source/smb.h samba-1.9.15/source/smb.h
  5001. --- last-version/source/smb.h    Sun Nov 12 13:21:29 1995
  5002. +++ samba-1.9.15/source/smb.h    Tue Nov 14 21:55:41 1995
  5003. @@ -767,7 +767,7 @@
  5004.  char *smb_trans2_data(char *buf);
  5005.  BOOL strequal(char *,char *);
  5006.  BOOL strcsequal(char *,char *);
  5007. -BOOL mask_match( char *str, char *regexp, int case_sig, BOOL autoext);
  5008. +BOOL mask_match( char *str, char *regexp, int case_sig, BOOL trans2);
  5009.  int dos_mode(int ,char *,struct stat *);
  5010.  char *timestring();
  5011.  BOOL ip_equal(struct in_addr ip1,struct in_addr ip2);
  5012. diff -u -r --new-file last-version/source/status.c samba-1.9.15/source/status.c
  5013. --- last-version/source/status.c    Sun Nov 12 13:08:59 1995
  5014. +++ samba-1.9.15/source/status.c    Mon Nov 13 15:53:03 1995
  5015. @@ -30,6 +30,15 @@
  5016.  extern int DEBUGLEVEL;
  5017.  extern FILE *dbf;
  5018.  
  5019. +static pstring Ucrit_username = "";                   /* added by OH */
  5020. +int            Ucrit_pid[100];  /* Ugly !!! */        /* added by OH */
  5021. +int            Ucrit_MaxPid=0;                        /* added by OH */
  5022. +unsigned int   Ucrit_IsActive = 0;                    /* added by OH */
  5023. +void           Ucrit_addUsername(pstring username);   /* added by OH */
  5024. +unsigned int   Ucrit_checkUsername(pstring username); /* added by OH */
  5025. +void           Ucrit_addPid(int pid);                 /* added by OH */
  5026. +unsigned int   Ucrit_checkPid(int pid);               /* added by OH */
  5027. +
  5028.  int main(int argc, char *argv[])
  5029.  {
  5030.    FILE *f;
  5031. @@ -42,6 +51,7 @@
  5032.    char *s;
  5033.    BOOL firstopen=True;
  5034.    BOOL processes_only=False;
  5035. +  int last_pid=0;
  5036.  
  5037.    charset_initialise();
  5038.  
  5039. @@ -53,7 +63,7 @@
  5040.      return(1);
  5041.    }
  5042.  
  5043. -  while ((c = getopt(argc, argv, "pds:")) != EOF) {
  5044. +  while ((c = getopt(argc, argv, "pdsu:")) != EOF) {
  5045.      switch (c) {
  5046.      case 'd':
  5047.        verbose = 1;
  5048. @@ -64,13 +74,18 @@
  5049.      case 's':
  5050.        strcpy(servicesf, optarg);
  5051.        break;
  5052. +    case 'u':                                       /* added by OH */
  5053. +      Ucrit_addUsername(optarg);                    /* added by OH */
  5054. +      break;
  5055.      default:
  5056. -      fprintf(stderr, "Usage: %s [-p] [-d] [-s configfile]\n", *argv);
  5057. +      fprintf(stderr, "Usage: %s [-d] [-p] [-s configfile] [-u username]\n", *argv); /* changed by OH */
  5058.        return (-1);
  5059.      }
  5060.    }
  5061.  
  5062. -  if (!lp_load(servicesf,True)) {
  5063. +
  5064. +
  5065. +  if (!lp_load(servicesf,False)) {
  5066.      fprintf(stderr, "Can't load %s - run testparm to debug it\n", servicesf);
  5067.      return (-1);
  5068.    }
  5069. @@ -97,28 +112,30 @@
  5070.  
  5071.    if (!processes_only) {
  5072.      printf("\nSamba version %s\n",VERSION);
  5073. -    
  5074. +
  5075.      printf("Service      uid      gid      pid     machine\n");
  5076.      printf("----------------------------------------------\n");
  5077.    }
  5078.  
  5079.    while (!feof(f))
  5080.      {
  5081. -      static int last_pid = 0;
  5082.        if (fread(&crec,sizeof(crec),1,f) != 1)
  5083.      break;
  5084. -      if (crec.magic == 0x280267 && process_exists(crec.pid)) {
  5085. +      if ( crec.magic == 0x280267 && process_exists(crec.pid) 
  5086. +           && Ucrit_checkUsername(uidtoname(crec.uid))                      /* added by OH */
  5087. +         )
  5088. +      {
  5089. +        Ucrit_addPid(crec.pid);                                             /* added by OH */
  5090.      if (processes_only) {
  5091.        if (last_pid != crec.pid)
  5092.          printf("%d\n",crec.pid);
  5093.        last_pid = crec.pid; /* XXXX we can still get repeats, have to
  5094.                    add a sort at some time */
  5095.      }
  5096. -    else
  5097. +    else      
  5098.        printf("%-10.10s   %-8s %-8s %5d   %-8s (%s) %s",
  5099.           crec.name,uidtoname(crec.uid),gidtoname(crec.gid),crec.pid,
  5100. -         crec.machine,crec.addr,
  5101. -         asctime(LocalTime(&crec.start,GMT_TO_LOCAL)));
  5102. +         crec.machine,crec.addr,asctime(LocalTime(&crec.start,0)));
  5103.        }
  5104.      }
  5105.    fclose(f);
  5106. @@ -155,9 +172,12 @@
  5107.      mode = IVAL(buf,4);
  5108.      pid = IVAL(buf,8);
  5109.  
  5110. +    if ( !Ucrit_checkPid(pid) )             /* added by OH */
  5111. +        continue;
  5112. +
  5113.      if (IVAL(buf,12) != LOCKING_VERSION || !process_exists(pid)) {
  5114.        if (unlink(lname)==0)
  5115. -    printf("Deleted stale share file %s\n",s);
  5116. +        printf("Deleted stale share file %s\n",s);
  5117.        continue;
  5118.      }
  5119.  
  5120. @@ -194,5 +214,38 @@
  5121.      printf("No locked files\n");
  5122.  
  5123.    return (0);
  5124. +}
  5125. +
  5126. +/* added by OH */
  5127. +void Ucrit_addUsername(pstring username)
  5128. +{
  5129. +  strcpy(Ucrit_username, username);
  5130. +  if(strlen(Ucrit_username) > 0)
  5131. +    Ucrit_IsActive = 1;
  5132. +}
  5133. +
  5134. +unsigned int Ucrit_checkUsername(pstring username)
  5135. +{
  5136. +  if ( !Ucrit_IsActive) return 1;
  5137. +  if (strcmp(Ucrit_username,username) ==0) return 1;
  5138. +  return 0;
  5139. +}
  5140. +
  5141. +void Ucrit_addPid(int pid)
  5142. +{
  5143. +  int i;
  5144. +  if ( !Ucrit_IsActive) return;
  5145. +  for (i=0;i<Ucrit_MaxPid;i++)
  5146. +    if( pid == Ucrit_pid[i] ) return;
  5147. +  Ucrit_pid[Ucrit_MaxPid++] = pid;
  5148. +}
  5149. +
  5150. +unsigned int   Ucrit_checkPid(int pid)
  5151. +{
  5152. +  int i;
  5153. +  if ( !Ucrit_IsActive) return 1;
  5154. +  for (i=0;i<Ucrit_MaxPid;i++)
  5155. +    if( pid == Ucrit_pid[i] ) return 1;
  5156. +  return 0;
  5157.  }
  5158.  
  5159. diff -u -r --new-file last-version/source/system.c samba-1.9.15/source/system.c
  5160. --- last-version/source/system.c    Thu Sep 21 21:01:05 1995
  5161. +++ samba-1.9.15/source/system.c    Mon Nov 13 17:35:06 1995
  5162. @@ -96,7 +96,7 @@
  5163.    do {
  5164.      if (tval) memcpy((void *)&t2,(void *)tval,sizeof(t2));
  5165.      errno = 0;
  5166. -    selrtn = select(255,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
  5167. +    selrtn = select(FD_SETSIZE,SELECT_CAST fds,NULL,NULL,tval?&t2:NULL);
  5168.    } while (selrtn<0 && errno == EINTR);
  5169.  
  5170.    return(selrtn);
  5171. diff -u -r --new-file last-version/source/trans2.c samba-1.9.15/source/trans2.c
  5172. --- last-version/source/trans2.c    Sat Nov 11 00:19:11 1995
  5173. +++ samba-1.9.15/source/trans2.c    Tue Nov 14 21:58:26 1995
  5174. @@ -300,7 +300,7 @@
  5175.  
  5176.        strcpy(fname,dname);      
  5177.  
  5178. -      if(mask_match(fname, mask, case_sensitive, False))
  5179. +      if(mask_match(fname, mask, case_sensitive, True))
  5180.      {
  5181.        BOOL isdots = (strequal(fname,"..") || strequal(fname,"."));
  5182.        if (dont_descend && !isdots)
  5183. diff -u -r --new-file last-version/source/username.c samba-1.9.15/source/username.c
  5184. --- last-version/source/username.c    Sat Sep  2 14:33:27 1995
  5185. +++ samba-1.9.15/source/username.c    Mon Nov 13 16:30:59 1995
  5186. @@ -202,19 +202,19 @@
  5187.      return(True);
  5188.  
  5189.  #ifdef NETGROUP
  5190. -      if (*p == '@')
  5191. +      if (*tok == '@')
  5192.      {
  5193.        static char *mydomain = NULL;
  5194.        if (mydomain == 0)
  5195.          yp_get_default_domain(&mydomain);
  5196.        
  5197.        DEBUG(5,("looking for user %s of domain %s in netgroup %s\n",
  5198. -           user, mydomain, p+1));
  5199. +           user, mydomain, &tok[1]));
  5200.        DEBUG(5,("innetgr is %s\n",
  5201. -           innetgr(p + 1, (char *) 0, user, mydomain)
  5202. +           innetgr(&tok[1], (char *) 0, user, mydomain)
  5203.             ? "TRUE" : "FALSE"));
  5204.        
  5205. -      if (innetgr(p + 1, (char *)0, user, mydomain))
  5206. +      if (innetgr(&tok[1], (char *)0, user, mydomain))
  5207.          return (True);
  5208.      }
  5209.  #endif
  5210. diff -u -r --new-file last-version/source/util.c samba-1.9.15/source/util.c
  5211. --- last-version/source/util.c    Sun Nov 12 13:21:27 1995
  5212. +++ samba-1.9.15/source/util.c    Tue Nov 14 22:09:36 1995
  5213. @@ -1043,6 +1043,20 @@
  5214.  }
  5215.  
  5216.  /*******************************************************************
  5217. +  case insensitive string compararison, length limited
  5218. +********************************************************************/
  5219. +int StrnCaseCmp(char *s, char *t, int n)
  5220. +{
  5221. +  while (n-- && *s && *t) {
  5222. +    if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
  5223. +    s++; t++;
  5224. +  }
  5225. +  if (n) return(tolower(*s) - tolower(*t));
  5226. +
  5227. +  return(0);
  5228. +}
  5229. +
  5230. +/*******************************************************************
  5231.    compare 2 strings 
  5232.  ********************************************************************/
  5233.  BOOL strequal(char *s1,char *s2)
  5234. @@ -2831,7 +2845,7 @@
  5235.  * simplified regexp that takes * and ? only. Case can be
  5236.  * significant or not.
  5237.  *********************************************************/
  5238. -BOOL mask_match( char *str, char *regexp, int case_sig, BOOL autoext)
  5239. +BOOL mask_match(char *str, char *regexp, int case_sig, BOOL trans2)
  5240.  {
  5241.    char *p;
  5242.    pstring p1, p2;
  5243. @@ -2860,34 +2874,31 @@
  5244.  
  5245.    DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
  5246.  
  5247. -  if ((p=strrchr(p1,'.')))
  5248. -    {
  5249. +  if (trans2) {
  5250. +    strcpy(ebase,p1);
  5251. +    strcpy(sbase,p2);
  5252. +  } else {
  5253. +    if ((p=strrchr(p1,'.'))) {
  5254.        *p = 0;
  5255.        strcpy(ebase,p1);
  5256.        strcpy(eext,p+1);
  5257. -    }
  5258. -  else
  5259. -    {
  5260. +    } else {
  5261.        strcpy(ebase,p1);
  5262. -      if (autoext)
  5263. -    strcpy(eext,"*");
  5264. -      else
  5265. -    eext[0] = 0;
  5266. +      eext[0] = 0;
  5267.      }
  5268.  
  5269. -  if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.')))
  5270. -    {
  5271. -      *p = 0;
  5272. -      strcpy(sbase,p2);
  5273. -      strcpy(sext,p+1);
  5274. -    }
  5275. -  else
  5276. -    {
  5277. -      strcpy(sbase,p2);
  5278. -      strcpy(sext,"");
  5279. -    }
  5280. +  if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
  5281. +    *p = 0;
  5282. +    strcpy(sbase,p2);
  5283. +    strcpy(sext,p+1);
  5284. +  } else {
  5285. +    strcpy(sbase,p2);
  5286. +    strcpy(sext,"");
  5287. +  }
  5288. +  }
  5289.  
  5290. -  matched = do_match(sbase,ebase,case_sig) && do_match(sext,eext,case_sig);
  5291. +  matched = do_match(sbase,ebase,case_sig) && 
  5292. +    (trans2 || do_match(sext,eext,case_sig));
  5293.  
  5294.    DEBUG(5,("mask_match returning %d\n", matched));
  5295.  
  5296. @@ -3487,8 +3498,8 @@
  5297.  BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
  5298.  {
  5299.    unsigned long a1,a2;
  5300. -  putip((char *)&a1,(char *)&ip1);
  5301. -  putip((char *)&a2,(char *)&ip2);
  5302. +  a1 = ntohl(ip1.s_addr);
  5303. +  a2 = ntohl(ip2.s_addr);
  5304.    return(a1 == a2);
  5305.  }
  5306.  
  5307. @@ -4042,6 +4053,10 @@
  5308.  ****************************************************************************/
  5309.  int initgroups(char *name,gid_t id)
  5310.  {
  5311. +#ifdef NO_SETGROUPS
  5312. +  /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
  5313. +  return(0);
  5314. +#else
  5315.    gid_t  grouplst[NGROUPS_MAX];
  5316.    int    i,j;
  5317.    struct group *g;
  5318. @@ -4068,6 +4083,7 @@
  5319.      }
  5320.    endgrent();
  5321.    return(setgroups(i,grouplst));
  5322. +#endif
  5323.  }
  5324.  #endif
  5325.  
  5326. diff -u -r --new-file last-version/source/version.h samba-1.9.15/source/version.h
  5327. --- last-version/source/version.h    Sun Nov 12 21:43:21 1995
  5328. +++ samba-1.9.15/source/version.h    Wed Nov 15 00:11:42 1995
  5329. @@ -1 +1 @@
  5330. -#define VERSION "1.9.14p5"
  5331. +#define VERSION "1.9.15"
  5332.